diff --git a/config/alfresco/application-context.xml b/config/alfresco/application-context.xml index 3d34d5eb42..3a7c42d3ba 100644 --- a/config/alfresco/application-context.xml +++ b/config/alfresco/application-context.xml @@ -34,6 +34,7 @@ + diff --git a/config/alfresco/wcm-services-context.xml b/config/alfresco/wcm-services-context.xml new file mode 100644 index 0000000000..b68ddefdaf --- /dev/null +++ b/config/alfresco/wcm-services-context.xml @@ -0,0 +1,70 @@ + + + + + + + + + org.alfresco.wcm.webproject.WebProjectService + + + + + + + + + + + + + + + + + + + + + + ${server.transaction.mode.readOnly} + ${server.transaction.mode.readOnly} + ${server.transaction.mode.readOnly} + ${server.transaction.mode.readOnly} + ${server.transaction.mode.default} + + + + + + + + + + + + + + + + + + + + + + + webprojects + + + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java b/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java index 8a7ea32de0..496c537c36 100644 --- a/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java +++ b/source/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java @@ -1,465 +1,471 @@ -/* - * 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.service; - -import java.util.Collection; - -import org.alfresco.mbeans.VirtServerRegistry; -import org.alfresco.repo.site.SiteService; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.action.ActionService; -import org.alfresco.service.cmr.attributes.AttributeService; -import org.alfresco.service.cmr.audit.AuditService; -import org.alfresco.service.cmr.avm.AVMService; -import org.alfresco.service.cmr.avm.deploy.DeploymentService; -import org.alfresco.service.cmr.avm.locking.AVMLockingService; -import org.alfresco.service.cmr.avmsync.AVMSyncService; -import org.alfresco.service.cmr.coci.CheckOutCheckInService; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.lock.LockService; -import org.alfresco.service.cmr.ml.ContentFilterLanguagesService; -import org.alfresco.service.cmr.ml.EditionService; -import org.alfresco.service.cmr.ml.MultilingualContentService; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.CopyService; -import org.alfresco.service.cmr.repository.CrossRepositoryCopyService; -import org.alfresco.service.cmr.repository.MimetypeService; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.ScriptService; -import org.alfresco.service.cmr.repository.TemplateService; -import org.alfresco.service.cmr.rule.RuleService; -import org.alfresco.service.cmr.search.CategoryService; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.cmr.security.AuthenticationService; -import org.alfresco.service.cmr.security.AuthorityService; -import org.alfresco.service.cmr.security.OwnableService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.tagging.TaggingService; -import org.alfresco.service.cmr.thumbnail.ThumbnailService; -import org.alfresco.service.cmr.version.VersionService; -import org.alfresco.service.cmr.view.ExporterService; -import org.alfresco.service.cmr.view.ImporterService; -import org.alfresco.service.cmr.workflow.WorkflowService; -import org.alfresco.service.descriptor.DescriptorService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; - - -/** - * Implementation of a Service Registry based on the definition of - * Services contained within a Spring Bean Factory. - * - * @author David Caruana - */ -public class ServiceDescriptorRegistry - implements BeanFactoryAware, ServiceRegistry -{ - // Bean Factory within which the registry lives - private BeanFactory beanFactory = null; - - - /* (non-Javadoc) - * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory) - */ - public void setBeanFactory(BeanFactory beanFactory) throws BeansException - { - this.beanFactory = beanFactory; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.service.ServiceRegistry#getServices() - */ - public Collection getServices() - { - // TODO: Implement - throw new UnsupportedOperationException(); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.service.ServiceRegistry#isServiceProvided(org.alfresco.repo.ref.QName) - */ - public boolean isServiceProvided(QName service) - { - // TODO: Implement - throw new UnsupportedOperationException(); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.service.ServiceRegistry#getService(org.alfresco.repo.ref.QName) - */ - public Object getService(QName service) - { - return beanFactory.getBean(service.getLocalName()); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getDescriptorService() - */ - public DescriptorService getDescriptorService() - { - return (DescriptorService)getService(DESCRIPTOR_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.service.ServiceRegistry#getNodeService() - */ - public NodeService getNodeService() - { - return (NodeService)getService(NODE_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.service.ServiceRegistry#getNodeService() - */ - public AuthenticationService getAuthenticationService() - { - return (AuthenticationService)getService(AUTHENTICATION_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.service.ServiceRegistry#getContentService() - */ - public ContentService getContentService() - { - return (ContentService)getService(CONTENT_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getMimetypeService() - */ - public MimetypeService getMimetypeService() - { - return (MimetypeService)getService(MIMETYPE_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.service.ServiceRegistry#getVersionService() - */ - public VersionService getVersionService() - { - return (VersionService)getService(VERSION_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.service.ServiceRegistry#getLockService() - */ - public LockService getLockService() - { - return (LockService)getService(LOCK_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.service.ServiceRegistry#getDictionaryService() - */ - public DictionaryService getDictionaryService() - { - return (DictionaryService)getService(DICTIONARY_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getSearchService() - */ - public SearchService getSearchService() - { - return (SearchService)getService(SEARCH_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getTransactionService() - */ - public TransactionService getTransactionService() - { - return (TransactionService)getService(TRANSACTION_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getRetryingTransactionHelper() - */ - public RetryingTransactionHelper getRetryingTransactionHelper() - { - return (RetryingTransactionHelper)getService(RETRYING_TRANSACTION_HELPER); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getCopyService() - */ - public CopyService getCopyService() - { - return (CopyService)getService(COPY_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getCheckOutCheckInService() - */ - public CheckOutCheckInService getCheckOutCheckInService() - { - return (CheckOutCheckInService)getService(COCI_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getCategoryService() - */ - public CategoryService getCategoryService() - { - return (CategoryService)getService(CATEGORY_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getNamespaceService() - */ - public NamespaceService getNamespaceService() - { - return (NamespaceService)getService(NAMESPACE_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getImporterService() - */ - public ImporterService getImporterService() - { - return (ImporterService)getService(IMPORTER_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getExporterService() - */ - public ExporterService getExporterService() - { - return (ExporterService)getService(EXPORTER_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getRuleService() - */ - public RuleService getRuleService() - { - return (RuleService)getService(RULE_SERVICE); - } - - /* - * (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getActionService() - */ - public ActionService getActionService() - { - return (ActionService)getService(ACTION_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getPermissionService() - */ - public PermissionService getPermissionService() - { - return (PermissionService)getService(PERMISSIONS_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getAuthorityService() - */ - public AuthorityService getAuthorityService() - { - return (AuthorityService)getService(AUTHORITY_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getTemplateService() - */ - public TemplateService getTemplateService() - { - return (TemplateService)getService(TEMPLATE_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getTemplateService() - */ - public FileFolderService getFileFolderService() - { - return (FileFolderService)getService(FILE_FOLDER_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getScriptService() - */ - public ScriptService getScriptService() - { - return (ScriptService)getService(SCRIPT_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getWorkflowService() - */ - public WorkflowService getWorkflowService() - { - return (WorkflowService)getService(WORKFLOW_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getWorkflowService() - */ - public AuditService getAuditService() - { - return (AuditService)getService(AUDIT_SERVICE); - } - - /** - * Get the AVMService. - * @return The AVMService or null if there is none. - */ - public AVMService getAVMService() - { - return (AVMService)getService(AVM_SERVICE); - } - - /** - * Get the AVMService. - * @return The AVMService or null if there is none. - */ - public AVMService getAVMLockingAwareService() - { - return (AVMService)getService(AVM_LOCKING_AWARE_SERVICE); - } - - /** - * Get the AVM Sync Service. - * @return The AVM Sync Service. - */ - public AVMSyncService getAVMSyncService() - { - return (AVMSyncService)getService(AVM_SYNC_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getOwnableService() - */ - public OwnableService getOwnableService() - { - return (OwnableService)getService(OWNABLE_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getPersonService() - */ - public PersonService getPersonService() - { - return (PersonService)getService(PERSON_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getSiteService() - */ - public SiteService getSiteService() - { - return (SiteService) getService(SITE_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getCrossRepositoryCopyService() - */ - public CrossRepositoryCopyService getCrossRepositoryCopyService() - { - return (CrossRepositoryCopyService)getService(CROSS_REPO_COPY_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getAttributeService() - */ - public AttributeService getAttributeService() - { - return (AttributeService)getService(ATTRIBUTE_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getContentFilterLanguagesService() - */ - public ContentFilterLanguagesService getContentFilterLanguagesService() - { - return (ContentFilterLanguagesService) getService(CONTENT_FILTER_LANGUAGES_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getAVMLockingService() - */ - public AVMLockingService getAVMLockingService() - { - return (AVMLockingService)getService(AVM_LOCKING_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getVirtServerRegistry() - */ - public VirtServerRegistry getVirtServerRegistry() - { - return (VirtServerRegistry)getService(VIRT_SERVER_REGISTRY); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getEditionService() - */ - public EditionService getEditionService() - { - return (EditionService) getService(EDITION_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getMultilingualContentService() - */ - public MultilingualContentService getMultilingualContentService() - { - return (MultilingualContentService) getService(MULTILINGUAL_CONTENT_SERVICE); - } - - /** - * @see org.alfresco.service.ServiceRegistry#getThumbnailService() - */ - public ThumbnailService getThumbnailService() - { - return (ThumbnailService)getService(THUMBNAIL_SERVICE); - } - - /** - * @see org.alfresco.service.ServiceRegistry#getTaggingService() - */ - public TaggingService getTaggingService() - { - return (TaggingService)getService(TAGGING_SERVICE); - } - - /* (non-Javadoc) - * @see org.alfresco.service.ServiceRegistry#getDeploymentService() - */ - public DeploymentService getDeploymentService() { - return (DeploymentService) getService(DEPLOYMENT_SERVICE); - - } - - -} +/* + * 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.service; + +import java.util.Collection; + +import org.alfresco.mbeans.VirtServerRegistry; +import org.alfresco.repo.site.SiteService; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.attributes.AttributeService; +import org.alfresco.service.cmr.audit.AuditService; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avm.deploy.DeploymentService; +import org.alfresco.service.cmr.avm.locking.AVMLockingService; +import org.alfresco.service.cmr.avmsync.AVMSyncService; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.ml.ContentFilterLanguagesService; +import org.alfresco.service.cmr.ml.EditionService; +import org.alfresco.service.cmr.ml.MultilingualContentService; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.CopyService; +import org.alfresco.service.cmr.repository.CrossRepositoryCopyService; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.ScriptService; +import org.alfresco.service.cmr.repository.TemplateService; +import org.alfresco.service.cmr.rule.RuleService; +import org.alfresco.service.cmr.search.CategoryService; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.cmr.security.OwnableService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.tagging.TaggingService; +import org.alfresco.service.cmr.thumbnail.ThumbnailService; +import org.alfresco.service.cmr.version.VersionService; +import org.alfresco.service.cmr.view.ExporterService; +import org.alfresco.service.cmr.view.ImporterService; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.descriptor.DescriptorService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.wcm.webproject.WebProjectService; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; + + +/** + * Implementation of a Service Registry based on the definition of + * Services contained within a Spring Bean Factory. + * + * @author David Caruana + */ +public class ServiceDescriptorRegistry + implements BeanFactoryAware, ServiceRegistry +{ + // Bean Factory within which the registry lives + private BeanFactory beanFactory = null; + + + /* (non-Javadoc) + * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory) + */ + public void setBeanFactory(BeanFactory beanFactory) throws BeansException + { + this.beanFactory = beanFactory; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.service.ServiceRegistry#getServices() + */ + public Collection getServices() + { + // TODO: Implement + throw new UnsupportedOperationException(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.service.ServiceRegistry#isServiceProvided(org.alfresco.repo.ref.QName) + */ + public boolean isServiceProvided(QName service) + { + // TODO: Implement + throw new UnsupportedOperationException(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.service.ServiceRegistry#getService(org.alfresco.repo.ref.QName) + */ + public Object getService(QName service) + { + return beanFactory.getBean(service.getLocalName()); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getDescriptorService() + */ + public DescriptorService getDescriptorService() + { + return (DescriptorService)getService(DESCRIPTOR_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.service.ServiceRegistry#getNodeService() + */ + public NodeService getNodeService() + { + return (NodeService)getService(NODE_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.service.ServiceRegistry#getNodeService() + */ + public AuthenticationService getAuthenticationService() + { + return (AuthenticationService)getService(AUTHENTICATION_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.service.ServiceRegistry#getContentService() + */ + public ContentService getContentService() + { + return (ContentService)getService(CONTENT_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getMimetypeService() + */ + public MimetypeService getMimetypeService() + { + return (MimetypeService)getService(MIMETYPE_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.service.ServiceRegistry#getVersionService() + */ + public VersionService getVersionService() + { + return (VersionService)getService(VERSION_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.service.ServiceRegistry#getLockService() + */ + public LockService getLockService() + { + return (LockService)getService(LOCK_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.service.ServiceRegistry#getDictionaryService() + */ + public DictionaryService getDictionaryService() + { + return (DictionaryService)getService(DICTIONARY_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getSearchService() + */ + public SearchService getSearchService() + { + return (SearchService)getService(SEARCH_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getTransactionService() + */ + public TransactionService getTransactionService() + { + return (TransactionService)getService(TRANSACTION_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getRetryingTransactionHelper() + */ + public RetryingTransactionHelper getRetryingTransactionHelper() + { + return (RetryingTransactionHelper)getService(RETRYING_TRANSACTION_HELPER); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getCopyService() + */ + public CopyService getCopyService() + { + return (CopyService)getService(COPY_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getCheckOutCheckInService() + */ + public CheckOutCheckInService getCheckOutCheckInService() + { + return (CheckOutCheckInService)getService(COCI_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getCategoryService() + */ + public CategoryService getCategoryService() + { + return (CategoryService)getService(CATEGORY_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getNamespaceService() + */ + public NamespaceService getNamespaceService() + { + return (NamespaceService)getService(NAMESPACE_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getImporterService() + */ + public ImporterService getImporterService() + { + return (ImporterService)getService(IMPORTER_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getExporterService() + */ + public ExporterService getExporterService() + { + return (ExporterService)getService(EXPORTER_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getRuleService() + */ + public RuleService getRuleService() + { + return (RuleService)getService(RULE_SERVICE); + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getActionService() + */ + public ActionService getActionService() + { + return (ActionService)getService(ACTION_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getPermissionService() + */ + public PermissionService getPermissionService() + { + return (PermissionService)getService(PERMISSIONS_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getAuthorityService() + */ + public AuthorityService getAuthorityService() + { + return (AuthorityService)getService(AUTHORITY_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getTemplateService() + */ + public TemplateService getTemplateService() + { + return (TemplateService)getService(TEMPLATE_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getTemplateService() + */ + public FileFolderService getFileFolderService() + { + return (FileFolderService)getService(FILE_FOLDER_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getScriptService() + */ + public ScriptService getScriptService() + { + return (ScriptService)getService(SCRIPT_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getWorkflowService() + */ + public WorkflowService getWorkflowService() + { + return (WorkflowService)getService(WORKFLOW_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getWorkflowService() + */ + public AuditService getAuditService() + { + return (AuditService)getService(AUDIT_SERVICE); + } + + /** + * Get the AVMService. + * @return The AVMService or null if there is none. + */ + public AVMService getAVMService() + { + return (AVMService)getService(AVM_SERVICE); + } + + /** + * Get the AVMService. + * @return The AVMService or null if there is none. + */ + public AVMService getAVMLockingAwareService() + { + return (AVMService)getService(AVM_LOCKING_AWARE_SERVICE); + } + + /** + * Get the AVM Sync Service. + * @return The AVM Sync Service. + */ + public AVMSyncService getAVMSyncService() + { + return (AVMSyncService)getService(AVM_SYNC_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getOwnableService() + */ + public OwnableService getOwnableService() + { + return (OwnableService)getService(OWNABLE_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getPersonService() + */ + public PersonService getPersonService() + { + return (PersonService)getService(PERSON_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getSiteService() + */ + public SiteService getSiteService() + { + return (SiteService) getService(SITE_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getCrossRepositoryCopyService() + */ + public CrossRepositoryCopyService getCrossRepositoryCopyService() + { + return (CrossRepositoryCopyService)getService(CROSS_REPO_COPY_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getAttributeService() + */ + public AttributeService getAttributeService() + { + return (AttributeService)getService(ATTRIBUTE_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getContentFilterLanguagesService() + */ + public ContentFilterLanguagesService getContentFilterLanguagesService() + { + return (ContentFilterLanguagesService) getService(CONTENT_FILTER_LANGUAGES_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getAVMLockingService() + */ + public AVMLockingService getAVMLockingService() + { + return (AVMLockingService)getService(AVM_LOCKING_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getVirtServerRegistry() + */ + public VirtServerRegistry getVirtServerRegistry() + { + return (VirtServerRegistry)getService(VIRT_SERVER_REGISTRY); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getEditionService() + */ + public EditionService getEditionService() + { + return (EditionService) getService(EDITION_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getMultilingualContentService() + */ + public MultilingualContentService getMultilingualContentService() + { + return (MultilingualContentService) getService(MULTILINGUAL_CONTENT_SERVICE); + } + + /** + * @see org.alfresco.service.ServiceRegistry#getThumbnailService() + */ + public ThumbnailService getThumbnailService() + { + return (ThumbnailService)getService(THUMBNAIL_SERVICE); + } + + /** + * @see org.alfresco.service.ServiceRegistry#getTaggingService() + */ + public TaggingService getTaggingService() + { + return (TaggingService)getService(TAGGING_SERVICE); + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getDeploymentService() + */ + public DeploymentService getDeploymentService() { + return (DeploymentService) getService(DEPLOYMENT_SERVICE); + + } + + /* (non-Javadoc) + * @see org.alfresco.service.ServiceRegistry#getWebProjectService() + */ + public WebProjectService getWebProjectService() { + return (WebProjectService) getService(WEBPROJECT_SERVICE); + } +} diff --git a/source/java/org/alfresco/sandbox/SandboxConstants.java b/source/java/org/alfresco/sandbox/SandboxConstants.java index 6063a4bda1..81da5db1e2 100644 --- a/source/java/org/alfresco/sandbox/SandboxConstants.java +++ b/source/java/org/alfresco/sandbox/SandboxConstants.java @@ -1,55 +1,39 @@ +/* + * 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" + */ /*----------------------------------------------------------------------------- -* Copyright 2007 Alfresco Inc. -* -* 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 received a copy of the text describing the FLOSS exception, -* and it is also available here: http://www.alfresco.com/legal/licensing -* -* * Author Jon Cox * File SandboxConstants.java *----------------------------------------------------------------------------*/ package org.alfresco.sandbox; -import org.alfresco.service.namespace.QName; /** -* AVM sandbox constants -*/ -public class SandboxConstants + * WCM sandbox constants + * + * @deprecated refer to org.alfresco.wcm.sandbox.SandboxConstants + */ +public class SandboxConstants extends org.alfresco.wcm.sandbox.SandboxConstants { - // system property keys for sandbox identification and DNS virtualisation mapping - public final static String PROP_BACKGROUND_LAYER = ".background-layer."; - public final static String PROP_SANDBOXID = ".sandbox-id."; - public final static String PROP_DNS = ".dns."; - public final static String PROP_SANDBOX_STORE_PREFIX = ".sandbox.store."; - - public final static QName PROP_SANDBOX_STAGING_MAIN = QName.createQName(null, ".sandbox.staging.main"); - public final static QName PROP_SANDBOX_STAGING_PREVIEW = QName.createQName(null, ".sandbox.staging.preview"); - public final static QName PROP_SANDBOX_AUTHOR_MAIN = QName.createQName(null, ".sandbox.author.main"); - public final static QName PROP_SANDBOX_AUTHOR_PREVIEW = QName.createQName(null, ".sandbox.author.preview"); - public final static QName PROP_SANDBOX_WORKFLOW_MAIN = QName.createQName(null, ".sandbox.workflow.main"); - public final static QName PROP_SANDBOX_WORKFLOW_PREVIEW = QName.createQName(null, ".sandbox.workflow.preview"); - public final static QName PROP_SANDBOX_AUTHOR_WORKFLOW_MAIN = QName.createQName(null, ".sandbox.author.workflow.main"); - public final static QName PROP_SANDBOX_AUTHOR_WORKFLOW_PREVIEW = QName.createQName(null, ".sandbox.author.workflow.preview"); - public final static QName PROP_WEBSITE_NAME = QName.createQName(null, ".website.name"); - public final static QName PROP_AUTHOR_NAME = QName.createQName(null, ".author.name"); - public final static QName PROP_WEB_PROJECT_NODE_REF = QName.createQName(null, ".web_project.noderef"); - public final static QName PROP_LINK_VALIDATION_REPORT = QName.createQName(null, ".link.validation.report"); - public final static QName PROP_LAST_DEPLOYMENT_ID = QName.createQName(null, ".deployment.id"); } diff --git a/source/java/org/alfresco/service/ServiceRegistry.java b/source/java/org/alfresco/service/ServiceRegistry.java index d4a825f206..8515ffc46e 100644 --- a/source/java/org/alfresco/service/ServiceRegistry.java +++ b/source/java/org/alfresco/service/ServiceRegistry.java @@ -1,423 +1,432 @@ -/* - * 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.service; - -import java.util.Collection; - -import org.alfresco.mbeans.VirtServerRegistry; -import org.alfresco.repo.site.SiteService; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.service.cmr.action.ActionService; -import org.alfresco.service.cmr.attributes.AttributeService; -import org.alfresco.service.cmr.audit.AuditService; -import org.alfresco.service.cmr.avm.AVMService; -import org.alfresco.service.cmr.avm.locking.AVMLockingService; -import org.alfresco.service.cmr.avmsync.AVMSyncService; -import org.alfresco.service.cmr.coci.CheckOutCheckInService; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.lock.LockService; -import org.alfresco.service.cmr.ml.ContentFilterLanguagesService; -import org.alfresco.service.cmr.ml.EditionService; -import org.alfresco.service.cmr.ml.MultilingualContentService; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.CopyService; -import org.alfresco.service.cmr.repository.CrossRepositoryCopyService; -import org.alfresco.service.cmr.repository.MimetypeService; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.ScriptService; -import org.alfresco.service.cmr.repository.TemplateService; -import org.alfresco.service.cmr.rule.RuleService; -import org.alfresco.service.cmr.search.CategoryService; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.cmr.security.AuthenticationService; -import org.alfresco.service.cmr.security.AuthorityService; -import org.alfresco.service.cmr.security.OwnableService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.tagging.TaggingService; -import org.alfresco.service.cmr.thumbnail.ThumbnailService; -import org.alfresco.service.cmr.version.VersionService; -import org.alfresco.service.cmr.view.ExporterService; -import org.alfresco.service.cmr.view.ImporterService; -import org.alfresco.service.cmr.avm.deploy.DeploymentService; -import org.alfresco.service.cmr.workflow.WorkflowService; -import org.alfresco.service.descriptor.DescriptorService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; - - -/** - * This interface represents the registry of public Repository Services. - * The registry provides meta-data about each service and provides - * access to the service interface. - * - * @author David Caruana - */ -@PublicService -public interface ServiceRegistry -{ - // Service Bean Names - - static final String SERVICE_REGISTRY = "ServiceRegistry"; - - static final QName REGISTRY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ServiceRegistry"); - static final QName DESCRIPTOR_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "DescriptorService"); - static final QName TRANSACTION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "TransactionService"); - static final QName RETRYING_TRANSACTION_HELPER = QName.createQName(NamespaceService.ALFRESCO_URI, "retryingTransactionHelper"); - static final QName AUTHENTICATION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AuthenticationService"); - static final QName NAMESPACE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NamespaceService"); - static final QName DICTIONARY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "DictionaryService"); - static final QName NODE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NodeService"); - static final QName CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentService"); - static final QName MIMETYPE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MimetypeService"); - static final QName CONTENT_FILTER_LANGUAGES_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentFilterLanguagesService"); - static final QName MULTILINGUAL_CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MultilingualContentService"); - static final QName EDITION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "EditionService"); - static final QName SEARCH_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SearchService"); - static final QName CATEGORY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CategoryService"); - static final QName COPY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CopyService"); - static final QName LOCK_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "LockService"); - static final QName VERSION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "VersionService"); - static final QName COCI_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CheckoutCheckinService"); - static final QName RULE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "RuleService"); - static final QName IMPORTER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ImporterService"); - static final QName EXPORTER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ExporterService"); - static final QName ACTION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ActionService"); - static final QName PERMISSIONS_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "PermissionService"); - static final QName AUTHORITY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AuthorityService"); - static final QName TEMPLATE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "TemplateService"); - static final QName FILE_FOLDER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "FileFolderService"); - static final QName SCRIPT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ScriptService"); - static final QName WORKFLOW_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "WorkflowService"); - static final QName AUDIT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AuditService"); - static final QName OWNABLE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "OwnableService"); - static final QName PERSON_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "PersonService"); - static final QName SITE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SiteService"); - static final QName AVM_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMService"); - static final QName AVM_LOCKING_AWARE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMLockingAwareService"); - static final QName AVM_SYNC_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMSyncService"); - static final QName CROSS_REPO_COPY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CrossRepositoryCopyService"); - static final QName ATTRIBUTE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AttributeService"); - static final QName AVM_LOCKING_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMLockingService"); - static final QName VIRT_SERVER_REGISTRY = QName.createQName(NamespaceService.ALFRESCO_URI, "VirtServerRegistry"); - static final QName THUMBNAIL_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ThumbnailService"); - static final QName TAGGING_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "TaggingService"); - static final QName DEPLOYMENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "DeploymentService"); - - /** - * Get the list of services provided by the Repository - * - * @return list of provided Services - */ - @NotAuditable - Collection getServices(); - - /** - * Is the specified service provided by the Repository? - * - * @param service name of service to test provision of - * @return true => provided, false => not provided - */ - @NotAuditable - boolean isServiceProvided(QName service); - - /** - * Get the specified service. - * - * @param service name of service to retrieve - * @return the service interface (must cast to interface as described in service meta-data) - */ - @NotAuditable - Object getService(QName service); - - /** - * @return the descriptor service - */ - @NotAuditable - DescriptorService getDescriptorService(); - - /** - * @return the transaction service - */ - @NotAuditable - TransactionService getTransactionService(); - - /** - * @return the transaction service - */ - @NotAuditable - RetryingTransactionHelper getRetryingTransactionHelper(); - - /** - * @return the namespace service (or null, if one is not provided) - */ - @NotAuditable - NamespaceService getNamespaceService(); - - /** - * @return the authentication service (or null, if one is not provided) - */ - @NotAuditable - AuthenticationService getAuthenticationService(); - - /** - * @return the node service (or null, if one is not provided) - */ - @NotAuditable - NodeService getNodeService(); - - /** - * @return the content service (or null, if one is not provided) - */ - @NotAuditable - ContentService getContentService(); - - /** - * @return the mimetype service (or null, if one is not provided) - */ - @NotAuditable - MimetypeService getMimetypeService(); - - /** - * @return the content filter languages service (or null, if one is not provided) - */ - @NotAuditable - ContentFilterLanguagesService getContentFilterLanguagesService(); - - /** - * @return the search service (or null, if one is not provided) - */ - @NotAuditable - SearchService getSearchService(); - - /** - * @return the version service (or null, if one is not provided) - */ - @NotAuditable - VersionService getVersionService(); - - /** - * @return the lock service (or null, if one is not provided) - */ - @NotAuditable - LockService getLockService(); - - /** - * @return the dictionary service (or null, if one is not provided) - */ - @NotAuditable - DictionaryService getDictionaryService(); - - /** - * @return the copy service (or null, if one is not provided) - */ - @NotAuditable - CopyService getCopyService(); - - /** - * @return the checkout / checkin service (or null, if one is not provided) - */ - @NotAuditable - CheckOutCheckInService getCheckOutCheckInService(); - - /** - * @return the category service (or null, if one is not provided) - */ - @NotAuditable - CategoryService getCategoryService(); - - /** - * @return the importer service or null if not present - */ - @NotAuditable - ImporterService getImporterService(); - - /** - * @return the exporter service or null if not present - */ - @NotAuditable - ExporterService getExporterService(); - - /** - * @return the rule service (or null, if one is not provided) - */ - @NotAuditable - RuleService getRuleService(); - - /** - * @return the action service (or null if one is not provided) - */ - @NotAuditable - ActionService getActionService(); - - /** - * @return the permission service (or null if one is not provided) - */ - @NotAuditable - PermissionService getPermissionService(); - - /** - * @return the authority service (or null if one is not provided) - */ - @NotAuditable - AuthorityService getAuthorityService(); - - /** - * @return the template service (or null if one is not provided) - */ - @NotAuditable - TemplateService getTemplateService(); - - /** - * @return the file-folder manipulation service (or null if one is not provided) - */ - @NotAuditable - FileFolderService getFileFolderService(); - - /** - * @return the script execution service (or null if one is not provided) - */ - @NotAuditable - ScriptService getScriptService(); - - /** - * @return the workflow service (or null if one is not provided) - */ - @NotAuditable - WorkflowService getWorkflowService(); - - /** - * @return the audit service (or null if one is not provided) - */ - @NotAuditable - AuditService getAuditService(); - - /** - * Get the AVMService. - * @return The AVM service (or null if one is not provided); - */ - @NotAuditable - AVMService getAVMService(); - - /** - * Get the AVMLockingAwareService. - * @return The AVM locking aware service (or null if one is not provided); - */ - @NotAuditable - AVMService getAVMLockingAwareService(); - - /** - * Get the AVM Sync Service. - * @return The AVM Sync Service. - */ - @NotAuditable - AVMSyncService getAVMSyncService(); - - /** - * Get the ownable service (or null if one is not provided) - * @return - */ - @NotAuditable - OwnableService getOwnableService(); - - /** - * Get the person service (or null if one is not provided) - * @return - */ - @NotAuditable - PersonService getPersonService(); - - /** - * Get the site service (or null if one is not provided) - * @return - */ - @NotAuditable - SiteService getSiteService(); - - /** - * Get the cross repository copy service (or null if one is not provided) - * @return - */ - @NotAuditable - CrossRepositoryCopyService getCrossRepositoryCopyService(); - - /** - * Get the attribute service (or null if one is not provided) - * @return - */ - @NotAuditable - AttributeService getAttributeService(); - - /** - * Get the AVM locking service (or null if one is not provided) - * @return - */ - @NotAuditable - AVMLockingService getAVMLockingService(); - - /** - * Get the Virtualisation Server registry service bean - * @return - */ - @NotAuditable - VirtServerRegistry getVirtServerRegistry(); - - /** - * Get the Multilingual Content Service - * @return - */ - @NotAuditable - MultilingualContentService getMultilingualContentService(); - - /** - * Get the Edition Service - * @return - */ - @NotAuditable - EditionService getEditionService(); - - /** - * Get the Thumbnail Service - * @return - */ - @NotAuditable - ThumbnailService getThumbnailService(); - - /** - * Get the Tagging Service - * @return - */ - @NotAuditable - TaggingService getTaggingService(); - - /** - * Get the Deployment Service - * @return the deployment service (or null, if one is not provided) - */ - @NotAuditable - DeploymentService getDeploymentService(); -} +/* + * 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.service; + +import java.util.Collection; + +import org.alfresco.mbeans.VirtServerRegistry; +import org.alfresco.repo.site.SiteService; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.attributes.AttributeService; +import org.alfresco.service.cmr.audit.AuditService; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avm.locking.AVMLockingService; +import org.alfresco.service.cmr.avmsync.AVMSyncService; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.ml.ContentFilterLanguagesService; +import org.alfresco.service.cmr.ml.EditionService; +import org.alfresco.service.cmr.ml.MultilingualContentService; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.CopyService; +import org.alfresco.service.cmr.repository.CrossRepositoryCopyService; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.ScriptService; +import org.alfresco.service.cmr.repository.TemplateService; +import org.alfresco.service.cmr.rule.RuleService; +import org.alfresco.service.cmr.search.CategoryService; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.cmr.security.OwnableService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.tagging.TaggingService; +import org.alfresco.service.cmr.thumbnail.ThumbnailService; +import org.alfresco.service.cmr.version.VersionService; +import org.alfresco.service.cmr.view.ExporterService; +import org.alfresco.service.cmr.view.ImporterService; +import org.alfresco.service.cmr.avm.deploy.DeploymentService; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.descriptor.DescriptorService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.wcm.webproject.WebProjectService; + + +/** + * This interface represents the registry of public Repository Services. + * The registry provides meta-data about each service and provides + * access to the service interface. + * + * @author David Caruana + */ +@PublicService +public interface ServiceRegistry +{ + // Service Bean Names + + static final String SERVICE_REGISTRY = "ServiceRegistry"; + + static final QName REGISTRY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ServiceRegistry"); + static final QName DESCRIPTOR_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "DescriptorService"); + static final QName TRANSACTION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "TransactionService"); + static final QName RETRYING_TRANSACTION_HELPER = QName.createQName(NamespaceService.ALFRESCO_URI, "retryingTransactionHelper"); + static final QName AUTHENTICATION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AuthenticationService"); + static final QName NAMESPACE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NamespaceService"); + static final QName DICTIONARY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "DictionaryService"); + static final QName NODE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NodeService"); + static final QName CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentService"); + static final QName MIMETYPE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MimetypeService"); + static final QName CONTENT_FILTER_LANGUAGES_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentFilterLanguagesService"); + static final QName MULTILINGUAL_CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MultilingualContentService"); + static final QName EDITION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "EditionService"); + static final QName SEARCH_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SearchService"); + static final QName CATEGORY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CategoryService"); + static final QName COPY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CopyService"); + static final QName LOCK_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "LockService"); + static final QName VERSION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "VersionService"); + static final QName COCI_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CheckoutCheckinService"); + static final QName RULE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "RuleService"); + static final QName IMPORTER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ImporterService"); + static final QName EXPORTER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ExporterService"); + static final QName ACTION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ActionService"); + static final QName PERMISSIONS_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "PermissionService"); + static final QName AUTHORITY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AuthorityService"); + static final QName TEMPLATE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "TemplateService"); + static final QName FILE_FOLDER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "FileFolderService"); + static final QName SCRIPT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ScriptService"); + static final QName WORKFLOW_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "WorkflowService"); + static final QName AUDIT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AuditService"); + static final QName OWNABLE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "OwnableService"); + static final QName PERSON_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "PersonService"); + static final QName SITE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SiteService"); + static final QName AVM_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMService"); + static final QName AVM_LOCKING_AWARE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMLockingAwareService"); + static final QName AVM_SYNC_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMSyncService"); + static final QName CROSS_REPO_COPY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CrossRepositoryCopyService"); + static final QName ATTRIBUTE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AttributeService"); + static final QName AVM_LOCKING_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AVMLockingService"); + static final QName VIRT_SERVER_REGISTRY = QName.createQName(NamespaceService.ALFRESCO_URI, "VirtServerRegistry"); + static final QName THUMBNAIL_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ThumbnailService"); + static final QName TAGGING_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "TaggingService"); + static final QName DEPLOYMENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "DeploymentService"); + static final QName WEBPROJECT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "WebProjectService"); + + /** + * Get the list of services provided by the Repository + * + * @return list of provided Services + */ + @NotAuditable + Collection getServices(); + + /** + * Is the specified service provided by the Repository? + * + * @param service name of service to test provision of + * @return true => provided, false => not provided + */ + @NotAuditable + boolean isServiceProvided(QName service); + + /** + * Get the specified service. + * + * @param service name of service to retrieve + * @return the service interface (must cast to interface as described in service meta-data) + */ + @NotAuditable + Object getService(QName service); + + /** + * @return the descriptor service + */ + @NotAuditable + DescriptorService getDescriptorService(); + + /** + * @return the transaction service + */ + @NotAuditable + TransactionService getTransactionService(); + + /** + * @return the transaction service + */ + @NotAuditable + RetryingTransactionHelper getRetryingTransactionHelper(); + + /** + * @return the namespace service (or null, if one is not provided) + */ + @NotAuditable + NamespaceService getNamespaceService(); + + /** + * @return the authentication service (or null, if one is not provided) + */ + @NotAuditable + AuthenticationService getAuthenticationService(); + + /** + * @return the node service (or null, if one is not provided) + */ + @NotAuditable + NodeService getNodeService(); + + /** + * @return the content service (or null, if one is not provided) + */ + @NotAuditable + ContentService getContentService(); + + /** + * @return the mimetype service (or null, if one is not provided) + */ + @NotAuditable + MimetypeService getMimetypeService(); + + /** + * @return the content filter languages service (or null, if one is not provided) + */ + @NotAuditable + ContentFilterLanguagesService getContentFilterLanguagesService(); + + /** + * @return the search service (or null, if one is not provided) + */ + @NotAuditable + SearchService getSearchService(); + + /** + * @return the version service (or null, if one is not provided) + */ + @NotAuditable + VersionService getVersionService(); + + /** + * @return the lock service (or null, if one is not provided) + */ + @NotAuditable + LockService getLockService(); + + /** + * @return the dictionary service (or null, if one is not provided) + */ + @NotAuditable + DictionaryService getDictionaryService(); + + /** + * @return the copy service (or null, if one is not provided) + */ + @NotAuditable + CopyService getCopyService(); + + /** + * @return the checkout / checkin service (or null, if one is not provided) + */ + @NotAuditable + CheckOutCheckInService getCheckOutCheckInService(); + + /** + * @return the category service (or null, if one is not provided) + */ + @NotAuditable + CategoryService getCategoryService(); + + /** + * @return the importer service or null if not present + */ + @NotAuditable + ImporterService getImporterService(); + + /** + * @return the exporter service or null if not present + */ + @NotAuditable + ExporterService getExporterService(); + + /** + * @return the rule service (or null, if one is not provided) + */ + @NotAuditable + RuleService getRuleService(); + + /** + * @return the action service (or null if one is not provided) + */ + @NotAuditable + ActionService getActionService(); + + /** + * @return the permission service (or null if one is not provided) + */ + @NotAuditable + PermissionService getPermissionService(); + + /** + * @return the authority service (or null if one is not provided) + */ + @NotAuditable + AuthorityService getAuthorityService(); + + /** + * @return the template service (or null if one is not provided) + */ + @NotAuditable + TemplateService getTemplateService(); + + /** + * @return the file-folder manipulation service (or null if one is not provided) + */ + @NotAuditable + FileFolderService getFileFolderService(); + + /** + * @return the script execution service (or null if one is not provided) + */ + @NotAuditable + ScriptService getScriptService(); + + /** + * @return the workflow service (or null if one is not provided) + */ + @NotAuditable + WorkflowService getWorkflowService(); + + /** + * @return the audit service (or null if one is not provided) + */ + @NotAuditable + AuditService getAuditService(); + + /** + * Get the AVMService. + * @return The AVM service (or null if one is not provided); + */ + @NotAuditable + AVMService getAVMService(); + + /** + * Get the AVMLockingAwareService. + * @return The AVM locking aware service (or null if one is not provided); + */ + @NotAuditable + AVMService getAVMLockingAwareService(); + + /** + * Get the AVM Sync Service. + * @return The AVM Sync Service. + */ + @NotAuditable + AVMSyncService getAVMSyncService(); + + /** + * Get the ownable service (or null if one is not provided) + * @return + */ + @NotAuditable + OwnableService getOwnableService(); + + /** + * Get the person service (or null if one is not provided) + * @return + */ + @NotAuditable + PersonService getPersonService(); + + /** + * Get the site service (or null if one is not provided) + * @return + */ + @NotAuditable + SiteService getSiteService(); + + /** + * Get the cross repository copy service (or null if one is not provided) + * @return + */ + @NotAuditable + CrossRepositoryCopyService getCrossRepositoryCopyService(); + + /** + * Get the attribute service (or null if one is not provided) + * @return + */ + @NotAuditable + AttributeService getAttributeService(); + + /** + * Get the AVM locking service (or null if one is not provided) + * @return + */ + @NotAuditable + AVMLockingService getAVMLockingService(); + + /** + * Get the Virtualisation Server registry service bean + * @return + */ + @NotAuditable + VirtServerRegistry getVirtServerRegistry(); + + /** + * Get the Multilingual Content Service + * @return + */ + @NotAuditable + MultilingualContentService getMultilingualContentService(); + + /** + * Get the Edition Service + * @return + */ + @NotAuditable + EditionService getEditionService(); + + /** + * Get the Thumbnail Service + * @return + */ + @NotAuditable + ThumbnailService getThumbnailService(); + + /** + * Get the Tagging Service + * @return + */ + @NotAuditable + TaggingService getTaggingService(); + + /** + * Get the Deployment Service + * @return the deployment service (or null, if one is not provided) + */ + @NotAuditable + DeploymentService getDeploymentService(); + + /** + * Get the WebProject Service + * @return + */ + @NotAuditable + WebProjectService getWebProjectService(); +} diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxConstants.java b/source/java/org/alfresco/wcm/sandbox/SandboxConstants.java new file mode 100644 index 0000000000..9857eb7d3a --- /dev/null +++ b/source/java/org/alfresco/wcm/sandbox/SandboxConstants.java @@ -0,0 +1,60 @@ +/* + * 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" + */ + +/*----------------------------------------------------------------------------- +* Author Jon Cox +* File SandboxConstants.java +*----------------------------------------------------------------------------*/ + +package org.alfresco.wcm.sandbox; + +import org.alfresco.service.namespace.QName; + +/** +* WCM sandbox constants +*/ +public class SandboxConstants +{ + // system property keys for sandbox identification and DNS virtualisation mapping + public final static String PROP_BACKGROUND_LAYER = ".background-layer."; + public final static String PROP_SANDBOXID = ".sandbox-id."; + public final static String PROP_DNS = ".dns."; + public final static String PROP_SANDBOX_STORE_PREFIX = ".sandbox.store."; + + public final static QName PROP_SANDBOX_STAGING_MAIN = QName.createQName(null, ".sandbox.staging.main"); + public final static QName PROP_SANDBOX_STAGING_PREVIEW = QName.createQName(null, ".sandbox.staging.preview"); + public final static QName PROP_SANDBOX_AUTHOR_MAIN = QName.createQName(null, ".sandbox.author.main"); + public final static QName PROP_SANDBOX_AUTHOR_PREVIEW = QName.createQName(null, ".sandbox.author.preview"); + public final static QName PROP_SANDBOX_WORKFLOW_MAIN = QName.createQName(null, ".sandbox.workflow.main"); + public final static QName PROP_SANDBOX_WORKFLOW_PREVIEW = QName.createQName(null, ".sandbox.workflow.preview"); + public final static QName PROP_SANDBOX_AUTHOR_WORKFLOW_MAIN = QName.createQName(null, ".sandbox.author.workflow.main"); + public final static QName PROP_SANDBOX_AUTHOR_WORKFLOW_PREVIEW = QName.createQName(null, ".sandbox.author.workflow.preview"); + public final static QName PROP_WEBSITE_NAME = QName.createQName(null, ".website.name"); + public final static QName PROP_AUTHOR_NAME = QName.createQName(null, ".author.name"); + public final static QName PROP_WEB_PROJECT_NODE_REF = QName.createQName(null, ".web_project.noderef"); + + public final static QName PROP_LINK_VALIDATION_REPORT = QName.createQName(null, ".link.validation.report"); + public final static QName PROP_LAST_DEPLOYMENT_ID = QName.createQName(null, ".deployment.id"); +} diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxFactory.java b/source/java/org/alfresco/wcm/sandbox/SandboxFactory.java new file mode 100644 index 0000000000..c9f082c927 --- /dev/null +++ b/source/java/org/alfresco/wcm/sandbox/SandboxFactory.java @@ -0,0 +1,634 @@ +/* + * 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.wcm.sandbox; + +import java.util.List; +import java.util.Map; + +import org.alfresco.config.JNDIConstants; +import org.alfresco.model.WCMAppModel; +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; +import org.alfresco.util.DNSNameMangler; +import org.alfresco.util.GUID; +import org.alfresco.wcm.util.WCMUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Helper factory to create WCM sandbox structures + * + * @author Kevin Roast + * @author janv + */ +public final class SandboxFactory extends WCMUtil +{ + private static Log logger = LogFactory.getLog(SandboxFactory.class); + + /** Services */ + private PermissionService permissionService; + private AVMService avmService; + private NodeService nodeService; + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public void setAvmService(AVMService avmService) + { + this.avmService = avmService; + } + + /** + * Private constructor + */ + private SandboxFactory() + { + } + + /** + * Create the staging sandbox for the named store. + * + * A staging sandbox is comprised of two stores, the first named 'storename-staging' with a + * preview store named 'storename-preview' layered over the staging store. + * + * Various store meta-data properties are set including: + * Identifier for store-types: .sandbox.staging.main and .sandbox.staging.preview + * Store-id: .sandbox-id. (unique across all stores in the sandbox) + * DNS: .dns. = + * Website Name: .website.name = website name + * + * @param storeId The store name to create the sandbox for. + * @param webProjectNodeRef The noderef for the webproject. + * @param branchStoreId The ID of the store to branch this staging store from. + */ + public SandboxInfo createStagingSandbox(String storeId, + NodeRef webProjectNodeRef, + String branchStoreId) + { + // create the 'staging' store for the website + String stagingStoreName = WCMUtil.buildStagingStoreName(storeId); + avmService.createStore(stagingStoreName); + + if (logger.isDebugEnabled()) + { + logger.debug("Created staging sandbox store: " + stagingStoreName); + } + + // we can either branch from an existing staging store or create a new structure + if (branchStoreId != null) + { + String branchStorePath = WCMUtil.buildStagingStoreName(branchStoreId) + ":/" + + JNDIConstants.DIR_DEFAULT_WWW; + avmService.createBranch(-1, branchStorePath, + stagingStoreName + ":/", JNDIConstants.DIR_DEFAULT_WWW); + } + else + { + // create the system directories 'www' and 'avm_webapps' + avmService.createDirectory(stagingStoreName + ":/", JNDIConstants.DIR_DEFAULT_WWW); + avmService.createDirectory(WCMUtil.buildStoreRootPath(stagingStoreName), + JNDIConstants.DIR_DEFAULT_APPBASE); + } + + + // set staging area permissions + setStagingPermissions(storeId, webProjectNodeRef); + + // Add permissions for layers + + // tag the store with the store type + avmService.setStoreProperty(stagingStoreName, + SandboxConstants.PROP_SANDBOX_STAGING_MAIN, + new PropertyValue(DataTypeDefinition.TEXT, null)); + avmService.setStoreProperty(stagingStoreName, + SandboxConstants.PROP_WEB_PROJECT_NODE_REF, + new PropertyValue(DataTypeDefinition.NODE_REF, webProjectNodeRef)); + + // tag the store with the DNS name property + tagStoreDNSPath(avmService, stagingStoreName, storeId); + + // snapshot the store + avmService.createSnapshot(stagingStoreName, null, null); + + + // create the 'preview' store for the website + String previewStoreName = WCMUtil.buildStagingPreviewStoreName(storeId); + avmService.createStore(previewStoreName); + + if (logger.isDebugEnabled()) + { + logger.debug("Created staging preview sandbox store: " + previewStoreName + + " above " + stagingStoreName); + } + + // create a layered directory pointing to 'www' in the staging area + avmService.createLayeredDirectory(WCMUtil.buildStoreRootPath(stagingStoreName), + previewStoreName + ":/", + JNDIConstants.DIR_DEFAULT_WWW); + + + // apply READ permissions for all users + //dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(previewStoreName)); + //permissionService.setPermission(dirRef, PermissionService.ALL_AUTHORITIES, PermissionService.READ, true); + + // tag the store with the store type + avmService.setStoreProperty(previewStoreName, + SandboxConstants.PROP_SANDBOX_STAGING_PREVIEW, + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(avmService, previewStoreName, storeId, "preview"); + + // The preview store depends on the main staging store (dist=1) + tagStoreBackgroundLayer(avmService,previewStoreName,stagingStoreName,1); + + // snapshot the store + avmService.createSnapshot(previewStoreName, null, null); + + + // tag all related stores to indicate that they are part of a single sandbox + final QName sandboxIdProp = QName.createQName(SandboxConstants.PROP_SANDBOXID + GUID.generate()); + + avmService.setStoreProperty(stagingStoreName, + sandboxIdProp, + new PropertyValue(DataTypeDefinition.TEXT, null)); + avmService.setStoreProperty(previewStoreName, + sandboxIdProp, + new PropertyValue(DataTypeDefinition.TEXT, null)); + + if (logger.isDebugEnabled()) + { + dumpStoreProperties(avmService, stagingStoreName); + dumpStoreProperties(avmService, previewStoreName); + } + + return new SandboxInfo( new String[] { stagingStoreName, previewStoreName } ); + } + + protected void setStagingPermissions(String storeId, NodeRef webProjectNodeRef) + { + String storeName = WCMUtil.buildStagingStoreName(storeId); + NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(storeName)); + + // Apply sepcific user permissions as set on the web project + // All these will be masked out + List userInfoRefs = nodeService.getChildAssocs( + webProjectNodeRef, WCMAppModel.ASSOC_WEBUSER, RegexQNamePattern.MATCH_ALL); + + for (ChildAssociationRef ref : userInfoRefs) + { + NodeRef userInfoRef = ref.getChildRef(); + String username = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERNAME); + String userrole = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERROLE); + + permissionService.setPermission(dirRef, username, userrole, true); + } + } + + public void setStagingPermissionMasks(String storeId) + { + String storeName = WCMUtil.buildStagingStoreName(storeId); + NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(storeName)); + + // Set store permission masks + String currentUser = AuthenticationUtil.getCurrentUserName(); + permissionService.setPermission(dirRef.getStoreRef(), currentUser, PermissionService.CHANGE_PERMISSIONS, true); + permissionService.setPermission(dirRef.getStoreRef(), currentUser, PermissionService.READ_PERMISSIONS, true); + permissionService.setPermission(dirRef.getStoreRef(), PermissionService.ALL_AUTHORITIES, PermissionService.READ, true); + + // apply READ permissions for all users + permissionService.setPermission(dirRef, PermissionService.ALL_AUTHORITIES, PermissionService.READ, true); + } + + public void updateStagingAreaManagers(String storeId, NodeRef webProjectNodeRef, final List managers) + { + // The stores have the mask set in updateSandboxManagers + String storeName = WCMUtil.buildStagingStoreName(storeId); + + NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(storeName)); + for (String manager : managers) + { + permissionService.setPermission(dirRef, manager, WCMUtil.ROLE_CONTENT_MANAGER, true); + + // give the manager change permissions permission in the staging area store + permissionService.setPermission(dirRef.getStoreRef(), manager, + PermissionService.CHANGE_PERMISSIONS, true); + permissionService.setPermission(dirRef.getStoreRef(), manager, + PermissionService.READ_PERMISSIONS, true); + } + } + + public void addStagingAreaUser(String storeId, String authority, String role) + { + // The stores have the mask set in updateSandboxManagers + String storeName = WCMUtil.buildStagingStoreName(storeId); + + NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(storeName)); + permissionService.setPermission(dirRef, authority, role, true); + } + + /** + * Create a user sandbox for the named store. + * + * A user sandbox is comprised of two stores, the first + * named 'storename--username' layered over the staging store with a preview store + * named 'storename--username--preview' layered over the main store. + * + * Various store meta-data properties are set including: + * Identifier for store-types: .sandbox.author.main and .sandbox.author.preview + * Store-id: .sandbox-id. (unique across all stores in the sandbox) + * DNS: .dns. = + * Website Name: .website.name = website name + * + * @param storeId The store id to create the sandbox for + * @param managers The list of authorities who have ContentManager role in the website + * @param username Username of the user to create the sandbox for + * @param role Role permission for the user + * @return Summary information regarding the sandbox + */ + public SandboxInfo createUserSandbox(String storeId, + List managers, + String username, + String role) + { + // create the user 'main' store + String userStoreName = WCMUtil.buildUserMainStoreName(storeId, username); + String previewStoreName = WCMUtil.buildUserPreviewStoreName(storeId, username); + + if (avmService.getStore(userStoreName) != null) + { + if (logger.isDebugEnabled()) + { + logger.debug("Not creating as store already exists: " + userStoreName); + } + return new SandboxInfo( new String[] { userStoreName, previewStoreName } ); + } + + avmService.createStore(userStoreName); + String stagingStoreName = WCMUtil.buildStagingStoreName(storeId); + if (logger.isDebugEnabled()) + logger.debug("Created user sandbox store: " + userStoreName + + " above staging store " + stagingStoreName); + + // create a layered directory pointing to 'www' in the staging area + avmService.createLayeredDirectory(WCMUtil.buildStoreRootPath(stagingStoreName), + userStoreName + ":/", + JNDIConstants.DIR_DEFAULT_WWW); + NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(userStoreName)); + + // Apply access mask to the store (ACls are applie to the staging area) + + // apply the user role permissions to the sandbox + String currentUser = AuthenticationUtil.getCurrentUserName(); + permissionService.setPermission(dirRef.getStoreRef(), currentUser, WCMUtil.ROLE_CONTENT_MANAGER, true); + permissionService.setPermission(dirRef.getStoreRef(), username, PermissionService.ALL_PERMISSIONS, true); + permissionService.setPermission(dirRef.getStoreRef(), PermissionService.ALL_AUTHORITIES, PermissionService.READ, true); + // apply the manager role permission for each manager in the web project + for (String manager : managers) + { + permissionService.setPermission(dirRef.getStoreRef(), manager, WCMUtil.ROLE_CONTENT_MANAGER, true); + } + + // tag the store with the store type + avmService.setStoreProperty(userStoreName, + SandboxConstants.PROP_SANDBOX_AUTHOR_MAIN, + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the base name of the website so that corresponding + // staging areas can be found. + avmService.setStoreProperty(userStoreName, + SandboxConstants.PROP_WEBSITE_NAME, + new PropertyValue(DataTypeDefinition.TEXT, storeId)); + + // tag the store, oddly enough, with its own store name for querying. + avmService.setStoreProperty(userStoreName, + QName.createQName(null, SandboxConstants.PROP_SANDBOX_STORE_PREFIX + userStoreName), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(avmService, userStoreName, storeId, username); + + // The user store depends on the main staging store (dist=1) + tagStoreBackgroundLayer(avmService,userStoreName,stagingStoreName,1); + + // snapshot the store + avmService.createSnapshot(userStoreName, null, null); + + // create the user 'preview' store + avmService.createStore(previewStoreName); + + if (logger.isDebugEnabled()) + { + logger.debug("Created user preview sandbox store: " + previewStoreName + + " above " + userStoreName); + } + + // create a layered directory pointing to 'www' in the user 'main' store + avmService.createLayeredDirectory(WCMUtil.buildStoreRootPath(userStoreName), + previewStoreName + ":/", + JNDIConstants.DIR_DEFAULT_WWW); + dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(previewStoreName)); + + // Apply access mask to the store (ACls are applied to the staging area) + + // apply the user role permissions to the sandbox + permissionService.setPermission(dirRef.getStoreRef(), currentUser, WCMUtil.ROLE_CONTENT_MANAGER, true); + permissionService.setPermission(dirRef.getStoreRef(), username, PermissionService.ALL_PERMISSIONS, true); + permissionService.setPermission(dirRef.getStoreRef(), PermissionService.ALL_AUTHORITIES, PermissionService.READ, true); + // apply the manager role permission for each manager in the web project + for (String manager : managers) + { + permissionService.setPermission(dirRef.getStoreRef(), manager, WCMUtil.ROLE_CONTENT_MANAGER, true); + } + + // tag the store with the store type + avmService.setStoreProperty(previewStoreName, + SandboxConstants.PROP_SANDBOX_AUTHOR_PREVIEW, + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with its own store name for querying. + avmService.setStoreProperty(previewStoreName, + QName.createQName(null, SandboxConstants.PROP_SANDBOX_STORE_PREFIX + previewStoreName), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(avmService, previewStoreName, storeId, username, "preview"); + + // The preview user store depends on the main user store (dist=1) + tagStoreBackgroundLayer(avmService,previewStoreName, userStoreName,1); + + // The preview user store depends on the main staging store (dist=2) + tagStoreBackgroundLayer(avmService,previewStoreName, stagingStoreName,2); + + + // snapshot the store + avmService.createSnapshot(previewStoreName, null, null); + + + // tag all related stores to indicate that they are part of a single sandbox + QName sandboxIdProp = QName.createQName(null, SandboxConstants.PROP_SANDBOXID + GUID.generate()); + avmService.setStoreProperty(userStoreName, + sandboxIdProp, + new PropertyValue(DataTypeDefinition.TEXT, null)); + avmService.setStoreProperty(previewStoreName, + sandboxIdProp, + new PropertyValue(DataTypeDefinition.TEXT, null)); + + if (logger.isDebugEnabled()) + { + dumpStoreProperties(avmService, userStoreName); + dumpStoreProperties(avmService, previewStoreName); + } + return new SandboxInfo( new String[] { userStoreName, previewStoreName } ); + } + + /** + * Create a workflow sandbox for the named store. + * + * Various store meta-data properties are set including: + * Identifier for store-types: .sandbox.workflow.main and .sandbox.workflow.preview + * Store-id: .sandbox-id. (unique across all stores in the sandbox) + * DNS: .dns. = + * Website Name: .website.name = website name + * + * @param storeId The id of the store to create a sandbox for + * @return Information about the sandbox + */ + public SandboxInfo createWorkflowSandbox(final String storeId) + { + final String stagingStoreName = WCMUtil.buildStagingStoreName(storeId); + + // create the workflow 'main' store + final String packageName = WCMUtil.STORE_WORKFLOW + "-" + GUID.generate(); + final String mainStoreName = WCMUtil.buildWorkflowMainStoreName(storeId, packageName); + + avmService.createStore(mainStoreName); + + if (logger.isDebugEnabled()) + { + logger.debug("Created workflow sandbox store: " + mainStoreName); + } + + // create a layered directory pointing to 'www' in the staging area + avmService.createLayeredDirectory(WCMUtil.buildStoreRootPath(stagingStoreName), + mainStoreName + ":/", + JNDIConstants.DIR_DEFAULT_WWW); + + // tag the store with the store type + avmService.setStoreProperty(mainStoreName, + SandboxConstants.PROP_SANDBOX_WORKFLOW_MAIN, + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the base name of the website so that corresponding + // staging areas can be found. + avmService.setStoreProperty(mainStoreName, + SandboxConstants.PROP_WEBSITE_NAME, + new PropertyValue(DataTypeDefinition.TEXT, storeId)); + + // tag the store, oddly enough, with its own store name for querying. + avmService.setStoreProperty(mainStoreName, + QName.createQName(null, SandboxConstants.PROP_SANDBOX_STORE_PREFIX + mainStoreName), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(avmService, mainStoreName, storeId, packageName); + + + // The main workflow store depends on the main staging store (dist=1) + tagStoreBackgroundLayer(avmService,mainStoreName, stagingStoreName ,1); + + // snapshot the store + avmService.createSnapshot(mainStoreName, null, null); + + // create the workflow 'preview' store + final String previewStoreName = WCMUtil.buildWorkflowPreviewStoreName(storeId, packageName); + + avmService.createStore(previewStoreName); + + if (logger.isDebugEnabled()) + { + logger.debug("Created workflow sandbox preview store: " + previewStoreName); + } + + // create a layered directory pointing to 'www' in the workflow 'main' store + avmService.createLayeredDirectory(WCMUtil.buildStoreRootPath(mainStoreName), + previewStoreName + ":/", + JNDIConstants.DIR_DEFAULT_WWW); + + // tag the store with the store type + avmService.setStoreProperty(previewStoreName, + SandboxConstants.PROP_SANDBOX_WORKFLOW_PREVIEW, + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with its own store name for querying. + avmService.setStoreProperty(previewStoreName, + QName.createQName(null, + SandboxConstants.PROP_SANDBOX_STORE_PREFIX + previewStoreName), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(avmService, previewStoreName, storeId, packageName, "preview"); + + + // The preview worfkflow store depends on the main workflow store (dist=1) + tagStoreBackgroundLayer(avmService,previewStoreName, mainStoreName,1); + + // The preview workflow store depends on the main staging store (dist=2) + tagStoreBackgroundLayer(avmService,previewStoreName, stagingStoreName,2); + + + // snapshot the store + avmService.createSnapshot(previewStoreName, null, null); + + + // tag all related stores to indicate that they are part of a single sandbox + final QName sandboxIdProp = QName.createQName(SandboxConstants.PROP_SANDBOXID + GUID.generate()); + avmService.setStoreProperty(mainStoreName, + sandboxIdProp, + new PropertyValue(DataTypeDefinition.TEXT, null)); + avmService.setStoreProperty(previewStoreName, + sandboxIdProp, + new PropertyValue(DataTypeDefinition.TEXT, null)); + + if (logger.isDebugEnabled()) + { + dumpStoreProperties(avmService, mainStoreName); + dumpStoreProperties(avmService, previewStoreName); + } + return new SandboxInfo( new String[] { mainStoreName, previewStoreName } ); + } + + /** + * Update the permissions for the list of sandbox managers applied to a user sandbox. + *

+ * Ensures that all managers in the list have full WRITE access to the specified user stores. + * + * @param storeId The store id of the sandbox to update + * @param managers The list of authorities who have ContentManager role in the web project + * @param username Username of the user sandbox to update + */ + public void updateSandboxManagers(final String storeId, final List managers, final String username) + { + final String userStoreName = WCMUtil.buildUserMainStoreName(storeId, username); + final String previewStoreName = WCMUtil.buildUserPreviewStoreName(storeId, username); + + // Apply masks to the stores + + // apply the manager role permission to the user main sandbox for each manager + NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(userStoreName)); + for (String manager : managers) + { + permissionService.setPermission(dirRef.getStoreRef(), manager, WCMUtil.ROLE_CONTENT_MANAGER, true); + } + + // apply the manager role permission to the user preview sandbox for each manager + dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(previewStoreName)); + for (String manager : managers) + { + permissionService.setPermission(dirRef.getStoreRef(), manager, WCMUtil.ROLE_CONTENT_MANAGER, true); + } + } + + /** + * Tag a named store with a DNS path meta-data attribute. + * The DNS meta-data attribute is set to the system path 'store:/www/avm_webapps' + * + * @param store Name of the store to tag + */ + private static void tagStoreDNSPath(AVMService avmService, String store, String... components) + { + String path = WCMUtil.buildSandboxRootPath(store); + // DNS name mangle the property name - can only contain value DNS characters! + String dnsProp = SandboxConstants.PROP_DNS + DNSNameMangler.MakeDNSName(components); + avmService.setStoreProperty(store, QName.createQName(null, dnsProp), + new PropertyValue(DataTypeDefinition.TEXT, path)); + } + + /** + * Tags a store with a property that indicates one of its + * backgroundStore layers, and the distance of that layer. + * This function must be called separately for each background + * store; for example the "mysite--alice--preview" store had + * as its immediate background "mysite--alice", which itself had + * as its background store "mysite", you'd make a sequence of + * calls like this: + * + *

+    *    tagStoreBackgroundLayer("mysite--alice",          "mysite",        1);
+    *    tagStoreBackgroundLayer("mysite--alice--preview", "mysite--alice", 1);
+    *    tagStoreBackgroundLayer("mysite--alice--preview", "mysite",        2);
+    *   
+ * + * This make it easy for other parts of the system to determine + * which stores depend on others directly or indirectly (which is + * useful for reloading virtualized webapps). + * + * @param store Name of the store to tag + * @param backgroundStore Name of store's background store + * @param distance Distance from store. + * The backgroundStore 'mysite' is 1 away from the store 'mysite--alice' + * but 2 away from the store 'mysite--alice--preview'. + */ + private static void tagStoreBackgroundLayer(AVMService avmService, + String store, + String backgroundStore, + int distance) + { + String prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + backgroundStore; + avmService.setStoreProperty(store, QName.createQName(null, prop_key), + new PropertyValue(DataTypeDefinition.INT, distance)); + } + + /** + * Debug helper method to dump the properties of a store + * + * @param store Store name to dump properties for + */ + private static void dumpStoreProperties(AVMService avmService, String store) + { + logger.debug("Store " + store); + Map props = avmService.getStoreProperties(store); + for (QName name : props.keySet()) + { + logger.debug(" " + name + ": " + props.get(name)); + } + } +} diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxInfo.java b/source/java/org/alfresco/wcm/sandbox/SandboxInfo.java new file mode 100644 index 0000000000..80202b7b7c --- /dev/null +++ b/source/java/org/alfresco/wcm/sandbox/SandboxInfo.java @@ -0,0 +1,57 @@ +/* + * 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.wcm.sandbox; + +import java.io.Serializable; + +/** +* Provides information about a WCM sandbox created by SandboxFactory. +*/ +public final class SandboxInfo implements Serializable +{ + private static final long serialVersionUID = 3615436375385857404L; + + String [] store_names_; + public SandboxInfo(String [] store_names) + { + store_names_ = store_names; + } + + /** + * A list of names of the stores within this sandbox. + * The "main" store should come first in this list; + * any other stores should appear in the order that + * they are overlaid on "main" (e.g.: any "preview" + * layers should come afterward, in "lowest first" order). + *

+ * Note: all sandboxes must have a "main" layer. + */ + public String [] getStoreNames() { return store_names_; } + + /** + * The name of the "main" store within this sandbox. + */ + public String getMainStoreName() { return store_names_[0]; } +} diff --git a/source/java/org/alfresco/wcm/util/WCMUtil.java b/source/java/org/alfresco/wcm/util/WCMUtil.java new file mode 100644 index 0000000000..96d5c4f567 --- /dev/null +++ b/source/java/org/alfresco/wcm/util/WCMUtil.java @@ -0,0 +1,716 @@ +/* + * 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 protected 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 protected License for more details. + + * You should have received a copy of the GNU General protected 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.wcm.util; + +import java.text.MessageFormat; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.alfresco.config.JNDIConstants; +import org.alfresco.mbeans.VirtServerRegistry; +import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ParameterCheck; +import org.alfresco.util.VirtServerUtils; +import org.alfresco.wcm.sandbox.SandboxConstants; + + +/** + * Helper methods and constants related to WCM directories, paths and store name manipulation. + * + * TODO refactor ... + * + * @author Ariel Backenroth + * @author Kevin Roast + */ +public class WCMUtil +{ + /** + * Extracts the store name from the avm path + * + * @param avmPath an absolute avm path + * + * @return the store name + */ + protected static String getStoreName(final String avmPath) + { + final int i = avmPath.indexOf(':'); + if (i == -1) + { + throw new IllegalArgumentException("path " + avmPath + " does not contain a store"); + } + return avmPath.substring(0, i); + } + + /** + * Extracts the web project store id from the (sandbox) store name + *

+ * For example, if the (sandbox) store name is: teststore--admin then the web project store id is: teststore + *

+ * Note: Although the staging sandbox store name is currently equivalent to the web project store id, it should + * be derived using 'buildStagingStoreName'. + * + * @param storeName the sandbox store id + * + * @return the web project store id + */ + protected static String getStoreId(final String storeName) + { + final int index = storeName.indexOf(WCMUtil.STORE_SEPARATOR); + return (index == -1 + ? storeName + : storeName.substring(0, index)); + } + + /** + * Extracts the store id from the avm path + * + * For example, if the avm path is: teststore--admin:/www/ROOT then the store id is: teststore + * + * @param avmPath an absolute avm path + * + * @return the store id. + */ + protected static String getStoreIdFromPath(final String avmPath) + { + return getStoreId(getStoreName(avmPath)); + } + + /** + * Indicates whether the store name describes a preview store. + * + * @param storeName the store name + * + * @return true if the store is a preview store, false otherwise. + */ + protected static boolean isPreviewStore(final String storeName) + { + return storeName.endsWith(WCMUtil.STORE_SEPARATOR + WCMUtil.STORE_PREVIEW); + } + + /** + * Indicates whether the store name describes a workflow store. + * + * @param storeName the store name + * + * @return true if the store is a workflow store, false otherwise. + */ + protected static boolean isWorkflowStore(String storeName) + { + if (WCMUtil.isPreviewStore(storeName)) + { + storeName = WCMUtil.getCorrespondingMainStoreName(storeName); + } + + return storeName.indexOf(STORE_SEPARATOR + STORE_WORKFLOW) != -1; + } + + /** + * Indicates whether the store name describes a user store. + * + * @param storeName the store name + * + * @return true if the store is a user store, false otherwise. + */ + protected static boolean isUserStore(String storeName) + { + if (WCMUtil.isPreviewStore(storeName)) + { + storeName = WCMUtil.getCorrespondingMainStoreName(storeName); + } + return storeName.indexOf(WCMUtil.STORE_SEPARATOR) != -1; + } + + /** + * Indicates whether the store name describes a main store. + * + * @param storeName the store name + * + * @return true if the store is a main store, false otherwise. + */ + protected static boolean isMainStore(String storeName) + { + return (storeName.indexOf(WCMUtil.STORE_SEPARATOR) == -1); + } + + /** + * Extracts the username from the store name. + * + * @param storeName the store name + * + * @return the username associated or null if this is a staging store. + */ + protected static String getUserName(String storeName) + { + if (WCMUtil.isPreviewStore(storeName)) + { + storeName = WCMUtil.getCorrespondingMainStoreName(storeName); + } + final int index = storeName.indexOf(WCMUtil.STORE_SEPARATOR); + return (index == -1 + ? null + : storeName.substring(index + WCMUtil.STORE_SEPARATOR.length())); + } + + /** + * Returns the corresponding main store name if this is a preview store name. + * + * @param storeName the preview store name. + * + * @return the corresponding main store name. + * + * @exception IllegalArgumentException if this is not a preview store name. + */ + protected static String getCorrespondingMainStoreName(final String storeName) + { + if (!WCMUtil.isPreviewStore(storeName)) + { + throw new IllegalArgumentException("store " + storeName + " is not a preview store"); + } + return storeName.substring(0, + (storeName.length() - + (WCMUtil.STORE_SEPARATOR + WCMUtil.STORE_PREVIEW).length())); + } + + /** + * Returns the corresponding preview store name if this is a main store name. + * + * @param storeName the main store name. + * + * @return the corresponding preview store name. + * + * @exception IllegalArgumentException if this is not a main store name. + */ + protected static String getCorrespondingPreviewStoreName(final String storeName) + { + if (WCMUtil.isPreviewStore(storeName)) + { + throw new IllegalArgumentException("store " + storeName + " is already a preview store"); + } + return storeName + WCMUtil.STORE_SEPARATOR + WCMUtil.STORE_PREVIEW; + } + + /** + * Returns the corresponding path in the main store name if this is a path in + * a preview store. + * + * @param avmPath an avm path within the main store. + * + * @return the corresponding path within the preview store. + * + * @exception IllegalArgumentException if this is not a path within the preview store. + */ + protected static String getCorrespondingPathInMainStore(final String avmPath) + { + String storeName = WCMUtil.getStoreName(avmPath); + storeName = WCMUtil.getCorrespondingMainStoreName(storeName); + return WCMUtil.getCorrespondingPath(avmPath, storeName); + } + + /** + * Returns the corresponding path in the preview store name if this is a path in + * a main store. + * + * @param avmPath an avm path within the main store. + * + * @return the corresponding path within the preview store. + * + * @exception IllegalArgumentException if this is not a path within the preview store. + */ + protected static String getCorrespondingPathInPreviewStore(final String avmPath) + { + String storeName = WCMUtil.getStoreName(avmPath); + storeName = WCMUtil.getCorrespondingPreviewStoreName(storeName); + return WCMUtil.getCorrespondingPath(avmPath, storeName); + } + + /** + * Returns the corresponding path in the store provided. + * + * @param avmPath an avm path + * @param otherStore the other store to return the corresponding path for + * + * @return the corresponding path within the supplied store + */ + protected static String getCorrespondingPath(final String avmPath, final String otherStore) + { + return (otherStore + ':' + WCMUtil.getStoreRelativePath(avmPath)); + } + + /** + * Returns the main staging store name for the specified store id. + * + * @param storeId store id to build staging store name for + * + * @return main staging store name for the specified store id + */ + protected static String buildStagingStoreName(final String storeId) + { + ParameterCheck.mandatoryString("storeId", storeId); + return storeId; + } + + /** + * Returns the preview store name for the specified store id. + * + * @param storeId store id to build preview store name for + * + * @return preview store name for the specified store id + */ + protected static String buildStagingPreviewStoreName(final String storeId) + { + return (WCMUtil.buildStagingStoreName(storeId) + WCMUtil.STORE_SEPARATOR + + WCMUtil.STORE_PREVIEW); + } + + /** + * Returns the user's main store name for a specific username + * + * @param storeId store id to build user store name for + * @param username of the user to build store name for + * + * @return the main store for the specified user and store id + */ + protected static String buildUserMainStoreName(final String storeId, + final String userName) + { + ParameterCheck.mandatoryString("userName", userName); + return (WCMUtil.buildStagingStoreName(storeId) + WCMUtil.STORE_SEPARATOR + + userName); + } + + /** + * Returns the preview store name for a specific username. + * + * @param storeId store id to build user preview store name for + * @param username of the user to build preview store name for + * + * @return the preview store for the specified user and store id + */ + protected static String buildUserPreviewStoreName(final String storeId, + final String username) + { + return (WCMUtil.buildUserMainStoreName(storeId, username) + WCMUtil.STORE_SEPARATOR + + WCMUtil.STORE_PREVIEW); + } + + /** + * Returns the store name for a specific workflow Id. + * + * @param storeId store id to build workflow store name for + * @param workflowId of the user to build workflow store name for + * + * @return the store for the specified workflow and store ids + */ + protected static String buildWorkflowMainStoreName(final String storeId, + final String workflowId) + { + ParameterCheck.mandatoryString("workflowId", workflowId); + return (WCMUtil.buildStagingStoreName(storeId) + WCMUtil.STORE_SEPARATOR + + workflowId); + } + + /** + * Returns the preview store name for a specific workflow Id. + * + * @param storeId store id to build preview workflow store name for + * @param workflowId of the user to build preview workflow store name for + * + * @return the store for the specified preview workflow and store ids + */ + protected static String buildWorkflowPreviewStoreName(final String storeId, + final String workflowId) + { + return (WCMUtil.buildWorkflowMainStoreName(storeId, workflowId) + + WCMUtil.STORE_SEPARATOR + WCMUtil.STORE_PREVIEW); + } + + /** + * Returns the root path for the specified store name + * + * eg. mystore -> mystore:/www + * + * @param storeName store to build root path for + * + * @return root path for the specified store name + */ + protected static String buildStoreRootPath(final String storeName) + { + ParameterCheck.mandatoryString("storeName", storeName); + return storeName + ":/" + JNDIConstants.DIR_DEFAULT_WWW; + } + + /** + * Returns the root path for the specified sandbox name + * + * * eg. mystore -> mystore:/www/avm_webapps + * + * @param storeName store to build root sandbox path for + * + * @return root sandbox path for the specified store name + */ + protected static String buildSandboxRootPath(final String storeName) + { + ParameterCheck.mandatoryString("storeName", storeName); + return storeName + ":/" + JNDIConstants.DIR_DEFAULT_WWW_APPBASE; + } + + /** + * Returns the root webapp path for the specified store and webapp name + * + * @param storeName store to build root webapp path for + * @param webapp webapp folder name + * + * @return the root webapp path for the specified store and webapp name + */ + protected static String buildStoreWebappPath(final String storeName, String webApp) + { + ParameterCheck.mandatoryString("webApp", webApp); + return WCMUtil.buildSandboxRootPath(storeName) + '/' + webApp; + } + + // TODO refactor ... + // assume for now that it is a store name rather than a path - eg. main rather than main:/ + protected static String buildStoreUrl(AVMService avmService, String storeName, String domain, String port) + { + ParameterCheck.mandatoryString("storeName", storeName); + + if (domain == null || port == null) + { + throw new IllegalArgumentException("Domain and port are mandatory."); + } + + return MessageFormat.format(JNDIConstants.PREVIEW_SANDBOX_URL, + lookupStoreDNS(avmService, storeName), + domain, + port); + } + + protected static String buildWebappUrl(AVMService avmService, final String storeName, final String webApp, String domain, String port) + { + ParameterCheck.mandatoryString("webApp", webApp); + return (webApp.equals(DIR_ROOT) + ? buildStoreUrl(avmService, storeName, domain, port) + : buildStoreUrl(avmService, storeName, domain, port) + '/' + webApp); + } + + protected static String buildAssetUrl(String assetPath, String domain, String port, String dns) + { + ParameterCheck.mandatoryString("assetPath", assetPath); + + if (domain == null || port == null || dns == null) + { + throw new IllegalArgumentException("Domain, port and dns name are mandatory."); + } + + if (assetPath.startsWith(JNDIConstants.DIR_DEFAULT_WWW_APPBASE)) + { + assetPath = assetPath.substring((JNDIConstants.DIR_DEFAULT_WWW_APPBASE).length()); + } + if (assetPath.startsWith('/' + DIR_ROOT)) + { + assetPath = assetPath.substring(('/' + DIR_ROOT).length()); + } + if (assetPath.length() == 0 || assetPath.charAt(0) != '/') + { + assetPath = '/' + assetPath; + } + + return MessageFormat.format(JNDIConstants.PREVIEW_ASSET_URL, dns, domain, port, assetPath); + } + + protected static String lookupStoreDNS(AVMService avmService, String store) + { + ParameterCheck.mandatoryString("store", store); + + final Map props = + avmService.queryStorePropertyKey(store, QName.createQName(null, SandboxConstants.PROP_DNS + '%')); + + return (props.size() == 1 + ? props.keySet().iterator().next().getLocalName().substring(SandboxConstants.PROP_DNS.length()) + : null); + } + + /** + * Converts the provided path to an absolute path within the avm. + * + * @param parentAVMPath used as the parent path if the provided path + * is relative, otherwise used to extract the parent path portion up until + * the webapp directory. + * @param path a path relative to the parentAVMPath path, or if it is + * absolute, it is relative to the sandbox used in the parentAVMPath. + * + * @return an absolute path within the avm using the paths provided. + */ + /* + protected static String buildPath(final String parentAVMPath, + final String path, + final PathRelation relation) + { + String parent = parentAVMPath; + if (path == null || path.length() == 0 || ".".equals(path) || "./".equals(path)) + { + return parent; + } + + if (path.charAt(0) == '/') + { + final Matcher m = relation.pattern().matcher(parent); + if (m.matches()) + { + parent = m.group(1); + } + } + else if (parent.charAt(parent.length() - 1) != '/') + { + parent = parent + '/'; + } + + return parent + path; + } + */ + + /** + * Returns a path relative to the store portion of the avm path. + * + * @param absoluteAVMPath an absolute path within the avm + * @return the path without the store prefix. + */ + protected static String getStoreRelativePath(final String absoluteAVMPath) + { + final Matcher m = STORE_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(1).length() != 0 ? m.group(1) : null; + } + + /** + * Returns a path relative to the webapp portion of the avm path. + * + * @param absoluteAVMPath an absolute path within the avm + * @return a relative path within the webapp. + */ + protected static String getWebappRelativePath(final String absoluteAVMPath) + { + final Matcher m = WEBAPP_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(3).length() != 0 ? m.group(3) : "/"; + } + + /** + * Returns the webapp within the path + * + * @param absoluteAVMPath the path from which to extract the webapp name + * + * @return an the webapp name contained within the path or null. + */ + protected static String getWebapp(final String absoluteAVMPath) + { + final Matcher m = WEBAPP_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(2).length() != 0 ? m.group(2) : null; + } + + /** + * Returns the path portion up the webapp + * + * @param absoluteAVMPath the path from which to extract the webapp path + * + * @return an absolute avm path to the webapp contained within + * the path or null. + */ + protected static String getWebappPath(final String absoluteAVMPath) + { + final Matcher m = WEBAPP_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(1).length() != 0 ? m.group(1) : null; + } + + /** + * Returns a path relative to the sandbox porition of the avm path. + * + * @param absoluteAVMPath an absolute path within the avm + * @return a relative path within the sandbox. + */ + protected static String getSandboxRelativePath(final String absoluteAVMPath) + { + final Matcher m = SANDBOX_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(2).length() != 0 ? m.group(2) : "/"; + } + + /** + * Returns the path portion up the sandbox + * + * @param absoluteAVMPath the path from which to extract the sandbox path + * + * @return an absolute avm path to the sandbox contained within + * the path or null. + */ + protected static String getSandboxPath(final String absoluteAVMPath) + { + final Matcher m = SANDBOX_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(1).length() != 0 ? m.group(1) : null; + } + + /** + * Creates all directories for a path if they do not already exist. + */ + /* + protected static void makeAllDirectories(AVMService avmService, final String avmDirectoryPath) + { + // LOGGER.debug("mkdir -p " + avmDirectoryPath); + String s = avmDirectoryPath; + final Stack dirNames = new Stack(); + while (s != null) + { + try + { + if (avmService.lookup(-1, s) != null) + { + // LOGGER.debug("path " + s + " exists"); + break; + } + } + catch (AVMNotFoundException avmfe) + { + } + final String[] sb = AVMNodeConverter.SplitBase(s); + s = sb[0]; + // LOGGER.debug("pushing " + sb[1]); + dirNames.push(sb); + } + + while (!dirNames.isEmpty()) + { + final String[] sb = dirNames.pop(); + // LOGGER.debug("creating " + sb[1] + " in " + sb[0]); + avmService.createDirectory(sb[0], sb[1]); + } + } + */ + + /** + * Update notification on the virtualisation server webapp as required for the specified path + * + * @param path Path to match against + * @param force True to force update of server even if path does not match + */ + protected static void updateVServerWebapp(VirtServerRegistry vServerRegistry, String path, boolean force) + { + if (force || VirtServerUtils.requiresUpdateNotification(path)) + { + final int webappIndex = path.indexOf('/', + path.indexOf(JNDIConstants.DIR_DEFAULT_APPBASE) + + JNDIConstants.DIR_DEFAULT_APPBASE.length() + 1); + + if (webappIndex != -1) + { + path = path.substring(0, webappIndex); + } + vServerRegistry.updateWebapp(-1, path, true); + } + } + + /** + * Removal notification on all the virtualisation server webapp as required by the specified path + * + * @param path Path to match against + * @param force True to force update of server even if path does not match + */ + protected static void removeAllVServerWebapps(VirtServerRegistry vServerRegistry, String path, boolean force) + { + if (force || VirtServerUtils.requiresUpdateNotification(path)) + { + final int webappIndex = path.indexOf('/', + path.indexOf(JNDIConstants.DIR_DEFAULT_APPBASE) + + JNDIConstants.DIR_DEFAULT_APPBASE.length() + 1); + + if (webappIndex != -1) + { + path = path.substring(0, webappIndex); + } + vServerRegistry.removeAllWebapps(-1, path, true); + } + } + + /** + * Removal notification on the virtualisation server webapp as required for the specified path + * + * @param path Path to match against + * @param force True to force update of server even if path does not match + */ + protected static void removeVServerWebapp(VirtServerRegistry vServerRegistry, String path, boolean force) + { + if (force || VirtServerUtils.requiresUpdateNotification(path)) + { + final int webappIndex = path.indexOf('/', + path.indexOf(JNDIConstants.DIR_DEFAULT_APPBASE) + + JNDIConstants.DIR_DEFAULT_APPBASE.length() + 1); + + if (webappIndex != -1) + { + path = path.substring(0, webappIndex); + } + vServerRegistry.removeWebapp(-1, path, true); + } + } + + protected static String getWebProjectsPath() + { + return "/"+SPACES_COMPANY_HOME_CHILDNAME+"/"+SPACES_WCM_CHILDNAME; + } + + private static final String SPACES_COMPANY_HOME_CHILDNAME = "app:company_home"; // should match repository property: spaces.company_home.childname + private static final String SPACES_WCM_CHILDNAME = "app:wcm"; // should match repository property: spaces.wcm.childname + + // Component Separator. + protected static final String STORE_SEPARATOR = "--"; + + // names of the stores representing the layers for an AVM website + //XXXarielb this should be private + protected final static String STORE_WORKFLOW = "workflow"; + protected final static String STORE_PREVIEW = "preview"; + + // servlet default webapp + // Note: this webapp is mapped to the URL path "" + public final static String DIR_ROOT = "ROOT"; + + protected final static String SPACE_ICON_WEBSITE = "space-icon-website"; + + // web user role permissions + public static final String ROLE_CONTENT_MANAGER = "ContentManager"; + public static final String ROLE_CONTENT_PUBLISHER = "ContentPublisher"; + public static final String ROLE_CONTENT_REVIEWER = "ContentReviewer"; + public static final String ROLE_CONTENT_CONTRIBUTOR = "ContentContributor"; + + // pattern for absolute AVM Path + private final static Pattern STORE_RELATIVE_PATH_PATTERN = + Pattern.compile("[^:]+:(.+)"); + + private final static Pattern WEBAPP_RELATIVE_PATH_PATTERN = + Pattern.compile("([^:]+:/" + JNDIConstants.DIR_DEFAULT_WWW + + "/" + JNDIConstants.DIR_DEFAULT_APPBASE + "/([^/]+))(.*)"); + + private final static Pattern SANDBOX_RELATIVE_PATH_PATTERN = + Pattern.compile("([^:]+:/" + JNDIConstants.DIR_DEFAULT_WWW + + "/" + JNDIConstants.DIR_DEFAULT_APPBASE + ")(.*)"); +} diff --git a/source/java/org/alfresco/wcm/webproject/WebProjectInfo.java b/source/java/org/alfresco/wcm/webproject/WebProjectInfo.java new file mode 100644 index 0000000000..aa4c98dd0b --- /dev/null +++ b/source/java/org/alfresco/wcm/webproject/WebProjectInfo.java @@ -0,0 +1,122 @@ +/* + * 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.wcm.webproject; + +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Web Project Information + * + * @author janv + */ +public interface WebProjectInfo +{ + /** + * Get the site node reference + * + * @return NodeRef site node reference, null if not set + */ + public NodeRef getNodeRef(); + + /** +  * Get the name + * + * @return String name + */ + public String getName(); + + /** + * Set the name + * + * @param name the name to set + */ + public void setName(String name); + + /** + * Get the web project store id + * + * @return the web project store id (generated from the passed DNS name) + */ + public String getStoreId(); + + /** + * Get the staging store name + * + * @return String staging store name + */ + public String getStagingStoreName(); + + /** + * Get the description + * + * @return String description + */ + public String getDescription(); + + /** + * Set the description + * + * @param description description + */ + public void setDescription(String description); + + /** + * Get the title + * + * @return the title + */ + public String getTitle(); + + /** + * Set the title + * + * @param title the title to set + */ + public void setTitle(String title); + + /** + * Get the default webapp + * + * @return the webapp name + */ + public String getDefaultWebApp(); + + /** + * Set the default webapp + * + * @param webApp the webapp name to set + */ + public void setDefaultWebApp(String defaultWebApp); + + /** + * @return true if this web project can also be used as a template + */ + public boolean isTemplate(); + + /** + * @param isTemplate set to true if this web project can also be used as a template + */ + public void setIsTemplate(boolean isTemplate); +} diff --git a/source/java/org/alfresco/wcm/webproject/WebProjectInfoImpl.java b/source/java/org/alfresco/wcm/webproject/WebProjectInfoImpl.java new file mode 100644 index 0000000000..a1436c5a51 --- /dev/null +++ b/source/java/org/alfresco/wcm/webproject/WebProjectInfoImpl.java @@ -0,0 +1,190 @@ +/* + * 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.wcm.webproject; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.wcm.util.WCMUtil; + +/** + * Web Project Information + * + * @author janv + */ +public class WebProjectInfoImpl extends WCMUtil implements WebProjectInfo +{ + /** Web Project node reference */ + private NodeRef nodeRef; + + /** Web Project name */ + private String name; + + /** Web Project title */ + private String title; + + /** Web Project description */ + private String description; + + /** Web Project store id (aka DNS name) */ + private String wpStoreId; + + /** Web Project default webApp name */ + private String defaultWebApp; + + /** Web Project true if the web project can also be used as template */ + private boolean isTemplate; + + + /** + * Constructor + * + * @param name name + * @param description description + * @param nodeRef web project node reference + */ + /*package*/ WebProjectInfoImpl(String name, String title, String description, String wpStoreId, String defaultWebApp, boolean isTemplate, NodeRef nodeRef) + { + this.name = name; + this.title = title; + this.description = description; + this.wpStoreId = wpStoreId; + this.defaultWebApp = defaultWebApp; + this.isTemplate = isTemplate; + this.nodeRef = nodeRef; + } + + /** + * Get the site node reference + * + * @return NodeRef site node reference, null if not set + */ + public NodeRef getNodeRef() + { + return nodeRef; + } + + /** + * Get the name + * + * @return String name + */ + public String getName() + { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) + { + this.name = name; + } + + /** + * @return the dnsName + */ + public String getStoreId() + { + return wpStoreId; + } + + /** + * Get the staging store name + * + * @return String staging store name + */ + public String getStagingStoreName() + { + return WCMUtil.buildStagingStoreName(getStoreId()); + } + + /** + * Get the description + * + * @return String description + */ + public String getDescription() + { + return description; + } + + /** + * Set the description + * + * @param description description + */ + public void setDescription(String description) + { + this.description = description; + } + + /** + * @return the title + */ + public String getTitle() + { + return title; + } + + /** + * @param title the title to set + */ + public void setTitle(String title) + { + this.title = title; + } + + /** + * @return the webApp + */ + public String getDefaultWebApp() + { + return defaultWebApp; + } + + /** + * @param webApp the webApp to set + */ + public void setDefaultWebApp(String defaultWebApp) + { + this.defaultWebApp = defaultWebApp; + } + + /** + * @return the useAsTemplate + */ + public boolean isTemplate() + { + return isTemplate; + } + + /** + * @param isTemplate the isTemplate to set + */ + public void setIsTemplate(boolean isTemplate) + { + this.isTemplate = isTemplate; + } +} diff --git a/source/java/org/alfresco/wcm/webproject/WebProjectService.java b/source/java/org/alfresco/wcm/webproject/WebProjectService.java new file mode 100644 index 0000000000..e4a9f8c493 --- /dev/null +++ b/source/java/org/alfresco/wcm/webproject/WebProjectService.java @@ -0,0 +1,403 @@ +package org.alfresco.wcm.webproject; + +import java.util.List; +import java.util.Map; + +import org.alfresco.service.cmr.repository.NodeRef; + + +/** + * Web Project Service fundamental API. + *

+ * This service API is designed to support the public facing Web Project APIs. + * + * @author janv + */ +public interface WebProjectService +{ + // + // Web project operations + // + + /** + * Create a new web project (with a default ROOT webapp) + *

+ * Note: the DNS name will be used to generate the web project store id, which can be subsequently retrieved via WebProjectInfo.getStoreId() + * + * @param dnsName DNS name (required, must be unique) + * @param name name (require, must be unique) + * @param title title + * @param description description + * @return WebProjectInfo the created web project info + */ + public WebProjectInfo createWebProject(String dnsName, String name, String title, String description); + + /** + * Create a new web project (with a default ROOT webapp) + *

+ * Note: the DNS name will be used to generate the web project store id, which can be subsequently retrieved via WebProjectInfo.getStoreId() + * + * @param dnsName DNS name (required, must be unique) + * @param name name (required, must be unique) + * @param title title + * @param description description + * @param sourceNodeRef web project node ref to branch from (can be null) + * @return WebProjectInfo the created web project info + */ + public WebProjectInfo createWebProject(String dnsName, String name, String title, String description, NodeRef sourceNodeRef); + + /** + * Create a new web project (with given default web app) + *

+ * Note: the DNS name will be used to generate the web project store id, which can be subsequently retrieved via WebProjectInfo.getStoreId() + * + * @param dnsName DNS name (must be unique) + * @param name name (must be unique) + * @param title title + * @param description description + * @param defaultWebApp default webapp (if null, will default to ROOT webapp) + * @param useAsTemplate true if this web project can be used as a template to branch from + * @param sourceNodeRef web project node ref to branch from (can be null) + * @return WebProjectInfo the created web project info + */ + public WebProjectInfo createWebProject(String dnsName, String name, String title, String description, String defaultWebApp, boolean useAsTemplate, NodeRef sourceNodeRef); + + /** + * Returns the Web Projects container + * + * @return NodeRef the node ref of the "Web Projects" container node + */ + public NodeRef getWebProjectsRoot(); + + /** + * Returns the Web Project for the given AVM path + * + * @param absoluteAVMPath the AVM path from which to determine the Web Project + * @return NodeRef the web project node ref for the path or null if it could not be determined + */ + public NodeRef findWebProjectNodeFromPath(String absoluteAVMPath); + + /** + * Returns the Web Project for the given AVM store name (sandbox store id) + * + * @param storeName the AVM store name (sandbox store id) from which to determine the Web Project + * @return NodeRef the web project node ref for the path or null if it could not be determined + */ + public NodeRef findWebProjectNodeFromStore(String storeName); + + /** + * List the available web projects for the current user + * + * @return List list of web project info + */ + public List listWebProjects(); + + /** + * List the web projects for the given user (based on the available web projects for the current user) + * + * @param userName user name + * @return List list of web project info + */ + public List listWebProjects(String userName); + + /** + * Return true if web project node ref is a web project + * + * @param wpNodeRef web project store id + * @return boolean true, if web project + */ + public boolean isWebProject(String wpStoreId); + + /** + * Return true if web project node ref is a web project + * + * @param wpNodeRef web project node ref + * @return boolean true, if web project + */ + public boolean isWebProject(NodeRef wpNodeRef); + + /** + * Gets web project info based on the store id of a web project + *

+ * Returns null if the web project can not be found + * + * @param wpStoreId web project store id + * @return WebProjectInfo web project info + */ + public WebProjectInfo getWebProject(String wpStoreId); + + /** + * Gets web project info based on the DM nodeRef of a web project + *

+ * Returns null if the web project can not be found + * + * @param wpNodeRef web project node ref + * @return WebProjectInfo web project info + */ + public WebProjectInfo getWebProject(NodeRef wpNodeRef); + + /** + * Update the web project info + *

+ * Note: the nodeRef and storeId (dnsName) of a web project cannot be updated once the web project has been created + * + * @param wpInfo web project info + */ + public void updateWebProject(WebProjectInfo wpInfo); + + /** + * Delete the web project + *

+ * If the web project does not exist, will log a warning and succeed + *

+ * Current user must be a content manager for the web project + * + * @param name web project store id + */ + public void deleteWebProject(String wpStoreId); + + /** + * Delete the web project + *

+ * If the web project does not exist, will log a warning and succeed + *

+ * Current user must be a content manager for the web project + *

+ * Note: this will cascade delete all sandboxes associated with a web project + * + * @param name web project node ref + */ + public void deleteWebProject(NodeRef wpNodeRef); + + // + // Web app operations + // + + /** + * Create webapp for the given web project. + *

+ * Current user must be a content manager for the web project + * + * @param wpStoreId web project store id + * @param name webapp name (must be unique within a web project) + * @param description webapp description + */ + public void createWebApp(String wpStoreId, String name, String description); + + /** + * Create webapp for the given web project. + *

+ * Current user must be a content manager for the web project + * + * @param wpNodeRef web project node ref + * @param name webapp name (must be unique within a web project) + * @param description webapp description + */ + public void createWebApp(NodeRef wpNodeRef, String name, String description); + + /** + * List webapps for the web project + * + * @param wpStoreId web project store id + * @return List list of webapp names + */ + public List listWebApps(String wpStoreId); + + /** + * List webapps for the web project + * + * @param wpNodeRef web project node ref + * @return List list of webapp names + */ + public List listWebApps(NodeRef wpNodeRef); + + /** + * Delete webapp from the given web project + *

+ * Current user must be a content manager for the web project + *

+ * Note: this will cascade delete all assets within a webapp + * + * @param wpStoreId web project store id + * @param name webapp name + */ + public void deleteWebApp(String wpStoreId, String name); + + /** + * Delete webapp from the given web project + *

+ * Current user must be a content manager for the web project + *

+ * Note: this will cascade delete all assets within a webapp + * + * @param wpNodeRef web project node ref + * @param name webapp name + */ + public void deleteWebApp(NodeRef wpNodeRef, String name); + + // + // Web user operations + // + + /** + * Returns true if the current user is a manager of this web project + *

+ * Note: This includes admin users but does not include the System user + * + * @param wpStoreId web project store id + * @return boolean true if the user is a manager (role = WCMUtil.ROLE_CONTENT_MANAGER), false otherwise + */ + public boolean isContentManager(String wpStoreId); + + /** + * Returns true if the current user is a manager of this web project + * + * @param wpNodeRef web project node ref + * @return boolean true if the user is a manager (role = WCMUtil.ROLE_CONTENT_MANAGER), false otherwise + */ + public boolean isContentManager(NodeRef wpNodeRef); + + /** + * Returns true if the user is a manager of this web project + *

+ * Note: This includes admin users but does not include the System user + * + * @param storeName web project store id + * @param username user name + * @return boolean true if the user is a manager, false otherwise + */ + public boolean isContentManager(String wpStoreId, String username); + + /** + * Returns true if the user is a manager of this web project + *

+ * Note: This includes admin users but does not include the System user + * + * @param wpNodeRef web project node ref + * @param userName user name + * @return boolean true if the user is a manager (role = WCMUtil.ROLE_CONTENT_MANAGER), false otherwise + */ + public boolean isContentManager(NodeRef wpNodeRef, String userName); + + /** + * List the web users of the web project + *

+ * Current user must be a content manager for the web project + * + * @param wpStoreId web project store id + * @return Map map of pairs + */ + public Map listWebUsers(String wpStoreId); + + /** + * List the web users of the web project + *

+ * Current user must be a content manager for the web project + * + * @param wpNodeRef web project node ref + * @return Map map of pairs + */ + public Map listWebUsers(NodeRef wpNodeRef); + + /** + * Get the number of web users invited to this web project + * + * @param wpNodeRef web project node ref + * @return int number of invited web users + */ + public int getWebUserCount(NodeRef wpNodeRef); + + /** + * Gets the role of the specified user + * + * @param wpStoreId web project store id + * @param userName user name + * @return String web project role for this user, null if no assigned role + */ + public String getWebUserRole(String wpStoreId, String userName); + + /** + * Gets the role of the specified user + * + * @param wpNodeRef web project node ref + * @param userName user name + * @return String web project role for this user, null if no assigned role + */ + public String getWebUserRole(NodeRef wpNodeRef, String userName); + + /** + * Indicates whether given user is a web user of the web project or not + * + * @param store id web project store id + * @param userName user name + * @return boolean true if the user is a web user of the web project, false otherwise + */ + public boolean isWebUser(String wpStoreId, String userName); + + /** + * Indicates whether given user is a web user of the web project or not + * + * @param wpNodeRef web project node ref + * @param userName user name + * @return boolean true if the user is a web user of the web project, false otherwise + */ + public boolean isWebUser(NodeRef wpNodeRef, String userName); + + /** + * Invite users/groups to web project + *

+ * Note: authority name can be user or group, although a group is flattened into a set of users + * + * @param wpStoreId web project store id + * @param userGroupRoles map of pairs + */ + public void inviteWebUsersGroups(String wpStoreId, Map userGroupRoles); + + /** + * Invite users/groups to web project + *

+ * Note: authority name can be user or group, although a group is flattened into a set of users + * + * @param wpNodeRef web project node ref + * @param userGroupRoles map of pairs + */ + public void inviteWebUsersGroups(NodeRef wpNodeRef, Map userGroupRoles); + + /** + * Invite user to web project + * + * @param wpStoreId web project store id + * @param userName user name (not a group) + * @param userRole web project role + */ + public void inviteWebUser(String wpStoreId, String userName, String userRole); + + /** + * Invite user to web project + * + * @param wpNodeRef web project node ref + * @param userName user name (not a group) + * @param userRole web project role + */ + public void inviteWebUser(NodeRef wpNodeRef, String userName, String userRole); + + /** + * Uninvite user from a web project + *

+ * Note: this will cascade delete the user's sandboxes without warning (even if there are modified items) + * + * @param wpStoreId web project store id + * @param userName user name + */ + public void uninviteWebUser(String wpStoreId, String userName); + + /** + * Uninvite user from a web project + *

+ * Note: this will cascade delete the user's sandboxes without warning (even if there are modified items) + * + * @param wpNodeRef web project node ref + * @param userName user name + */ + public void uninviteWebUser(NodeRef wpNodeRef, String userName); +} diff --git a/source/java/org/alfresco/wcm/webproject/WebProjectServiceImpl.java b/source/java/org/alfresco/wcm/webproject/WebProjectServiceImpl.java new file mode 100644 index 0000000000..297f83781b --- /dev/null +++ b/source/java/org/alfresco/wcm/webproject/WebProjectServiceImpl.java @@ -0,0 +1,1413 @@ +/* + * 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.wcm.webproject; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.mbeans.VirtServerRegistry; +import org.alfresco.model.ApplicationModel; +import org.alfresco.model.ContentModel; +import org.alfresco.model.WCMAppModel; +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport; +import org.alfresco.repo.transaction.TransactionListenerAdapter; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avm.locking.AVMLockingService; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; +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.AuthorityService; +import org.alfresco.service.cmr.security.AuthorityType; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; +import org.alfresco.util.DNSNameMangler; +import org.alfresco.util.ParameterCheck; +import org.alfresco.wcm.sandbox.SandboxConstants; +import org.alfresco.wcm.sandbox.SandboxFactory; +import org.alfresco.wcm.sandbox.SandboxInfo; +import org.alfresco.wcm.util.WCMUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Web Project Service Implementation + * + * @author janv + */ +public class WebProjectServiceImpl extends WCMUtil implements WebProjectService +{ + /** Logger */ + private static Log logger = LogFactory.getLog(WebProjectServiceImpl.class); + + /** The DM store where web projects are kept */ + public static final StoreRef WEBPROJECT_STORE = new StoreRef("workspace://SpacesStore"); + + /** The web projects root node reference */ + private NodeRef webProjectsRootNodeRef; // note: WCM is not currently MT-enabled (so this is OK) + + /** Services */ + private NodeService nodeService; + private SearchService searchService; + private AVMService avmService; + private AVMLockingService avmLockingService; + private AuthorityService authorityService; + private PermissionService permissionService; + private PersonService personService; + + private SandboxFactory sandboxFactory; + private VirtServerRegistry virtServerRegistry; + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + public void setAvmService(AVMService avmService) + { + this.avmService = avmService; + } + + public void setAvmLockingService(AVMLockingService avmLockingService) + { + this.avmLockingService = avmLockingService; + } + + public void setAuthorityService(AuthorityService authorityService) + { + this.authorityService = authorityService; + } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public void setPersonService(PersonService personService) + { + this.personService = personService; + } + + public void setSandboxFactory(SandboxFactory sandboxFactory) + { + this.sandboxFactory = sandboxFactory; + } + + public void setVirtServerRegistry(VirtServerRegistry virtServerRegistry) + { + this.virtServerRegistry = virtServerRegistry; + } + + + /* (non-Javadoc) + * @see org.alfresco.wcm.WebProjectService#createWebProject(java.lang.String, java.lang.String, java.lang.String, java.lang.String) + */ + public WebProjectInfo createWebProject(String dnsName, String name, String title, String description) + { + return createWebProject(dnsName, name, title, description, null, false, null); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.WebProjectService#createWebProject(java.lang.String, java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef) + */ + public WebProjectInfo createWebProject(String dnsName, String name, String title, String description, NodeRef sourceNodeRef) + { + return createWebProject(dnsName, name, title, description, null, false, sourceNodeRef); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.WebProjectService#createWebProject(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, boolean, org.alfresco.service.cmr.repository.NodeRef) + */ + public WebProjectInfo createWebProject(String dnsName, String name, String title, String description, String defaultWebApp, boolean useAsTemplate, NodeRef sourceNodeRef) + { + // Generate web project store id (an AVM store name) + String wpStoreId = DNSNameMangler.MakeDNSName(dnsName); + + if (wpStoreId.indexOf(WCMUtil.STORE_SEPARATOR) != -1) + { + throw new AlfrescoRuntimeException("Unexpected store id '"+wpStoreId+"' - should not contain '"+WCMUtil.STORE_SEPARATOR+"'"); + } + + if (wpStoreId.indexOf(":") != -1) + { + throw new AlfrescoRuntimeException("Unexpected store id '"+wpStoreId+"' - should not contain ':'"); + } + + // create the website space in the correct parent folder + Map props = new HashMap(1); + props.put(ContentModel.PROP_NAME, name); + + ChildAssociationRef childAssocRef = nodeService.createNode( + getWebProjectsRoot(), + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(name)), + WCMAppModel.TYPE_AVMWEBFOLDER, + props); + + NodeRef wpNodeRef = childAssocRef.getChildRef(); + + + // apply the uifacets aspect - icon, title and description props + Map uiFacetsProps = new HashMap(4); + uiFacetsProps.put(ApplicationModel.PROP_ICON, WCMUtil.SPACE_ICON_WEBSITE); + uiFacetsProps.put(ContentModel.PROP_TITLE, title); + uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, description); + nodeService.addAspect(wpNodeRef, ApplicationModel.ASPECT_UIFACETS, uiFacetsProps); + + // use as template source flag + nodeService.setProperty(wpNodeRef, WCMAppModel.PROP_ISSOURCE, useAsTemplate); + + // set the default webapp name for the project + defaultWebApp = (defaultWebApp != null && defaultWebApp.length() != 0) ? defaultWebApp : WCMUtil.DIR_ROOT; + nodeService.setProperty(wpNodeRef, WCMAppModel.PROP_DEFAULTWEBAPP, defaultWebApp); + + // set the property on the node to reference the root AVM store + nodeService.setProperty(wpNodeRef, WCMAppModel.PROP_AVMSTORE, wpStoreId); + + // branch from source web project, if supplied + String branchStoreId = null; + if (sourceNodeRef != null) + { + branchStoreId = (String)nodeService.getProperty(sourceNodeRef, WCMAppModel.PROP_AVMSTORE); + } + + // create the AVM staging store to represent the newly created location website + sandboxFactory.createStagingSandbox(wpStoreId, wpNodeRef, branchStoreId); // ignore return + + // create the default webapp folder under the hidden system folders + if (branchStoreId == null) + { + String stagingStore = WCMUtil.buildStagingStoreName(wpStoreId); + String stagingStoreRoot = WCMUtil.buildSandboxRootPath(stagingStore); + avmService.createDirectory(stagingStoreRoot, defaultWebApp); + avmService.addAspect(AVMNodeConverter.ExtendAVMPath(stagingStoreRoot, defaultWebApp), WCMAppModel.ASPECT_WEBAPP); + } + + // now the sandbox is created set the permissions masks for the store + sandboxFactory.setStagingPermissionMasks(wpStoreId); + + // set the property on the node to reference the root AVM store + nodeService.setProperty(wpNodeRef, WCMAppModel.PROP_AVMSTORE, wpStoreId); + + // inform the locking service about this new instance + avmLockingService.addWebProject(wpStoreId); + + // Snapshot the store with the empty webapp + avmService.createSnapshot(wpStoreId, null, null); + + // break the permissions inheritance on the web project node so that only assigned users can access it + permissionService.setInheritParentPermissions(wpNodeRef, false); + + inviteWebUser(wpNodeRef, AuthenticationUtil.getCurrentEffectiveUserName(), WCMUtil.ROLE_CONTENT_MANAGER); + + // Bind the post-commit transaction listener with data required for virtualization server notification + CreateWebProjectTransactionListener tl = new CreateWebProjectTransactionListener(wpStoreId); + AlfrescoTransactionSupport.bindListener(tl); + + if (logger.isInfoEnabled()) + { + logger.info("Created web project: " + wpNodeRef + " (store id: " + wpStoreId + ")"); + } + + // Return created web project info + WebProjectInfo wpInfo = new WebProjectInfoImpl(name, title, description, wpStoreId, defaultWebApp, useAsTemplate, wpNodeRef); + return wpInfo; + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#createWebApp(java.lang.String, java.lang.String, java.lang.String) + */ + public void createWebApp(String wpStoreId, String webAppName, String webAppDescription) + { + createWebApp(findWebProjectNodeFromStore(wpStoreId), webAppName, webAppDescription); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#createWebApp(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String) + */ + public void createWebApp(NodeRef wpNodeRef, final String webAppName, final String webAppDescription) + { + WebProjectInfo wpInfo = getWebProject(wpNodeRef); + + if (isContentManager(wpNodeRef)) + { + // get AVM store name of the staging sandbox + final String stagingStoreId = wpInfo.getStagingStoreName(); + + AuthenticationUtil.runAs(new RunAsWork() + { + public Object doWork() throws Exception + { + final String parent = WCMUtil.buildSandboxRootPath(stagingStoreId); + avmService.createDirectory(parent, webAppName); + + String path = AVMNodeConverter.ExtendAVMPath(parent, webAppName); + avmService.addAspect(path, ApplicationModel.ASPECT_UIFACETS); + avmService.addAspect(path, WCMAppModel.ASPECT_WEBAPP); + + if (webAppDescription != null && webAppDescription.length() != 0) + { + avmService.setNodeProperty(path, + ContentModel.PROP_DESCRIPTION, + new PropertyValue(DataTypeDefinition.TEXT, + webAppDescription)); + } + + // Snapshot the store with the empty webapp + avmService.createSnapshot(stagingStoreId, null, null); + + return null; + } + }, AuthenticationUtil.getSystemUserName()); + + if (logger.isInfoEnabled()) + { + logger.info("Created web app: "+webAppName+" (store id: "+wpInfo.getStoreId()+")"); + } + } + else + { + throw new AccessDeniedException("Only content managers may create new webapp '"+webAppName+"' (store id: "+wpInfo.getStoreId()+")"); + } + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#listWebApps(java.lang.String) + */ + public List listWebApps(String wpStoreId) + { + return listWebApps(findWebProjectNodeFromStore(wpStoreId)); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#listWebApps(org.alfresco.service.cmr.repository.NodeRef) + */ + public List listWebApps(NodeRef wpNodeRef) + { + WebProjectInfo wpInfo = getWebProject(wpNodeRef); + + String path = WCMUtil.buildSandboxRootPath(wpInfo.getStagingStoreName()); + Map folders = avmService.getDirectoryListing(-1, path); + + List webAppNames = new ArrayList(folders.size()); + webAppNames.addAll(folders.keySet()); + return webAppNames; + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#deleteWebApp(java.lang.String, java.lang.String) + */ + public void deleteWebApp(String wpStoreId, String webAppName) + { + deleteWebApp(findWebProjectNodeFromStore(wpStoreId), webAppName); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#deleteWebApp(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) + */ + public void deleteWebApp(NodeRef wpNodeRef, final String webAppName) + { + ParameterCheck.mandatoryString("webAppName", webAppName); + + WebProjectInfo wpInfo = getWebProject(wpNodeRef); + + if (webAppName.equals(wpInfo.getDefaultWebApp())) + { + throw new AlfrescoRuntimeException("Cannot delete default webapp '"+webAppName+"' (store id: "+wpInfo.getStoreId()+")"); + } + else if (isContentManager(wpInfo.getNodeRef())) + { + // get AVM store name of the staging sandbox + final String wpStoreId = wpInfo.getStoreId(); + + AuthenticationUtil.runAs(new RunAsWork() + { + public Object doWork() throws Exception + { + final String parent = WCMUtil.buildSandboxRootPath(wpStoreId); + + avmService.removeNode(parent, webAppName); + + // Snapshot the store with the webapp removed + avmService.createSnapshot(wpStoreId, null, null); + + return null; + } + }, AuthenticationUtil.getSystemUserName()); + + if (logger.isInfoEnabled()) + { + logger.info("Deleted web app: "+webAppName+" (store id: "+wpStoreId+")"); + } + } + else + { + throw new AccessDeniedException("Only content managers may delete webapp '"+webAppName+"' (web project: "+wpNodeRef+")"); + } + } + + /** + * Get the node reference that is the web projects root + * + * @return NodeRef node reference + */ + public NodeRef getWebProjectsRoot() + { + if (this.webProjectsRootNodeRef == null) + { + // Get the root 'web projects' folder + ResultSet resultSet = this.searchService.query(WEBPROJECT_STORE, SearchService.LANGUAGE_LUCENE, "PATH:\""+WCMUtil.getWebProjectsPath()+"\""); + if (resultSet.length() == 0) + { + // No root web projects folder exists + throw new AlfrescoRuntimeException("No root 'Web Projects' folder exists (is WCM enabled ?)"); + } + else if (resultSet.length() != 1) + { + // More than one root web projects folder exits + throw new AlfrescoRuntimeException("More than one root 'Web Projects' folder exists"); + } + + this.webProjectsRootNodeRef = resultSet.getNodeRef(0); + } + + return this.webProjectsRootNodeRef; + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#listWebProjects() + */ + public List listWebProjects() + { + NodeRef wpRoot = getWebProjectsRoot(); + + Set nodeTypeQNames = new HashSet(1); + nodeTypeQNames.add(WCMAppModel.TYPE_AVMWEBFOLDER); + List webProjects = nodeService.getChildAssocs(wpRoot, nodeTypeQNames); + + List result = new ArrayList(webProjects.size()); + for (ChildAssociationRef childAssocRefs : webProjects) + { + result.add(getWebProject(childAssocRefs.getChildRef())); + } + + return result; + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#listWebProjects(java.lang.String) + */ + public List listWebProjects(String userName) + { + List webProjects = listWebProjects(); + List result = new ArrayList(webProjects.size()); + for (WebProjectInfo webProject : webProjects) + { + if (isWebUser(webProject.getNodeRef(), userName) == true) + { + result.add(webProject); + } + } + return result; + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#isWebProject(java.lang.String) + */ + public boolean isWebProject(String wpStoreId) + { + NodeRef wpNodeRef = findWebProjectNodeFromStore(wpStoreId); + if (wpNodeRef == null) + { + return false; + } + return isWebProject(wpNodeRef); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#isWebProject(org.alfresco.service.cmr.repository.NodeRef) + */ + public boolean isWebProject(NodeRef wpNodeRef) + { + if (wpNodeRef == null) + { + return false; + } + + try + { + return (WCMAppModel.TYPE_AVMWEBFOLDER.equals(nodeService.getType(wpNodeRef))); + } + catch (InvalidNodeRefException e) + { + return false; + } + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#getWebProject(java.lang.String) + */ + public WebProjectInfo getWebProject(String wpStoreId) + { + WebProjectInfo result = null; + + // Get the web project node + NodeRef wpNodeRef = findWebProjectNodeFromStore(wpStoreId); + if (wpNodeRef != null) + { + // Create the web project info + result = getWebProject(wpNodeRef); + } + + // Return the web project info + return result; + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#getWebProject(org.alfresco.service.cmr.repository.NodeRef) + */ + public WebProjectInfo getWebProject(NodeRef wpNodeRef) + { + if (! isWebProject(wpNodeRef)) + { + throw new IllegalArgumentException(wpNodeRef + " is not a web project"); + } + + // Get the properties + Map properties = this.nodeService.getProperties(wpNodeRef); + + String name = (String)properties.get(ContentModel.PROP_NAME); + String title = (String)properties.get(ContentModel.PROP_TITLE); + String description = (String)properties.get(ContentModel.PROP_DESCRIPTION); + String wpStoreId = (String)properties.get(WCMAppModel.PROP_AVMSTORE); + String defaultWebApp = (String)properties.get(WCMAppModel.PROP_DEFAULTWEBAPP); + Boolean useAsTemplate = (Boolean)properties.get(WCMAppModel.PROP_ISSOURCE); + + // Create and return the web project info + WebProjectInfo wpInfo = new WebProjectInfoImpl(name, title, description, wpStoreId, defaultWebApp, useAsTemplate, wpNodeRef); + return wpInfo; + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#updateWebProject(org.alfresco.wcm.webproject.WebProjectInfo) + */ + public void updateWebProject(WebProjectInfo wpInfo) + { + NodeRef wpNodeRef = findWebProjectNodeFromStore(wpInfo.getStoreId()); + if (wpNodeRef == null) + { + throw new AlfrescoRuntimeException("Cannot update web project '" + wpInfo.getStoreId() + "' because it does not exist."); + } + + // Note: the site preset and short name can not be updated + + // Update the properties of the site - note: cannot change storeId or wpNodeRef + Map properties = this.nodeService.getProperties(wpNodeRef); + + properties.put(ContentModel.PROP_NAME, wpInfo.getName()); + properties.put(ContentModel.PROP_TITLE, wpInfo.getTitle()); + properties.put(ContentModel.PROP_DESCRIPTION, wpInfo.getDescription()); + properties.put(WCMAppModel.PROP_DEFAULTWEBAPP, wpInfo.getDefaultWebApp()); + properties.put(WCMAppModel.PROP_ISSOURCE, wpInfo.isTemplate()); + + this.nodeService.setProperties(wpNodeRef, properties); + + if (logger.isDebugEnabled()) + { + logger.debug("Updated web project: " + wpNodeRef + " (store id: " + wpInfo.getStoreId() + ")"); + } + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#deleteWebProject(java.lang.String) + */ + public void deleteWebProject(String wpStoreId) + { + NodeRef wpNodeRef = findWebProjectNodeFromStore(wpStoreId); + if (wpNodeRef != null) + { + deleteWebProject(wpNodeRef); + } + else + { + // by definition, the current user is not a content manager since the web project does not exist (or is not visible) + throw new AccessDeniedException("Only content managers may delete a web project"); + } + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#deleteWebProject(org.alfresco.service.cmr.repository.NodeRef) + */ + public void deleteWebProject(final NodeRef wpNodeRef) + { + if (! isContentManager(wpNodeRef)) + { + // the current user is not a content manager since the web project does not exist (or is not visible) + throw new AccessDeniedException("Only content managers may delete web project"); + } + + // delete all attached website sandboxes in reverse order to the layering + final String wpStoreId = (String)nodeService.getProperty(wpNodeRef, WCMAppModel.PROP_AVMSTORE); + + if (wpStoreId != null) + { + // Notifiy virtualization server about removing this website + // + // Implementation note: + // + // Because the removal of virtual webapps in the virtualization + // server is recursive, it only needs to be given the name of + // the main staging store. + // + // This notification must occur *prior* to purging content + // within the AVM because the virtualization server must list + // the avm_webapps dir in each store to discover which + // virtual webapps must be unloaded. The virtualization + // server traverses the sandbox's stores in most-to-least + // dependent order, so clients don't have to worry about + // accessing a preview layer whose main layer has been torn + // out from under it. + // + // It does not matter what webapp name we give here, so "/ROOT" + // is as sensible as anything else. It's all going away. + + String sandbox = WCMUtil.buildStagingStoreName(wpStoreId); + String path = WCMUtil.buildStoreWebappPath(sandbox, "/ROOT"); + + WCMUtil.removeAllVServerWebapps(virtServerRegistry, path, true); + + // get the list of users who have a sandbox in the website + final Map existingUserRoles = listWebUsers(wpNodeRef); + + AuthenticationUtil.runAs(new RunAsWork() + { + public Object doWork() throws Exception + { + for (Map.Entry userRole : existingUserRoles.entrySet()) + { + String username = userRole.getKey(); + + // delete the preview store for this user + deleteStore(WCMUtil.buildUserPreviewStoreName(wpStoreId, username)); + + // delete the main store for this user + deleteStore(WCMUtil.buildUserMainStoreName(wpStoreId, username)); + } + + // remove the main staging and preview stores + deleteStore(WCMUtil.buildStagingPreviewStoreName(wpStoreId)); + deleteStore(WCMUtil.buildStagingStoreName(wpStoreId)); + + // delete the web project node itself + nodeService.deleteNode(wpNodeRef); + + return null; + } + }, AuthenticationUtil.getSystemUserName()); + + if (logger.isInfoEnabled()) + { + logger.info("Deleted web project: " + wpNodeRef + " (store id: " + wpStoreId + ")"); + } + } + } + + /** + * Delete a store, checking for its existence first. + * + * @param store + */ + private void deleteStore(final String store) + { + // check it exists before we try to remove it + if (avmService.getStore(store) != null) + { + avmService.purgeStore(store); + } + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#isContentManager(java.lang.String) + */ + public boolean isContentManager(String storeName) + { + return isContentManager(storeName, AuthenticationUtil.getCurrentEffectiveUserName()); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.WebProjectService#isContentManager(java.lang.String, java.lang.String) + */ + public boolean isContentManager(String storeName, String userName) + { + String wpStoreId = WCMUtil.getStoreId(storeName); + PropertyValue pValue = avmService.getStoreProperty(wpStoreId, SandboxConstants.PROP_WEB_PROJECT_NODE_REF); + + if (pValue != null) + { + NodeRef wpNodeRef = (NodeRef) pValue.getValue(DataTypeDefinition.NODE_REF); + return isContentManager(wpNodeRef, userName); + } + else + { + return false; + } + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#isContentManager(org.alfresco.service.cmr.repository.NodeRef) + */ + public boolean isContentManager(NodeRef wpNodeRef) + { + return isContentManager(wpNodeRef, AuthenticationUtil.getCurrentEffectiveUserName()); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#isContentManager(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) + */ + public boolean isContentManager(NodeRef wpNodeRef, String userName) + { + String userRole = getWebUserRole(wpNodeRef, userName); + return WCMUtil.ROLE_CONTENT_MANAGER.equals(userRole); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#isWebUser(java.lang.String, java.lang.String) + */ + public boolean isWebUser(String storeName, String username) + { + String wpStoreId = WCMUtil.getStoreId(storeName); + PropertyValue pValue = avmService.getStoreProperty(wpStoreId, SandboxConstants.PROP_WEB_PROJECT_NODE_REF); + + if (pValue != null) + { + NodeRef wpNodeRef = (NodeRef) pValue.getValue(DataTypeDefinition.NODE_REF); + return isWebUser(wpNodeRef, username); + } + else + { + return false; + } + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#isWebUser(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) + */ + public boolean isWebUser(NodeRef wpNodeRef, String userName) + { + String userRole = getWebUserRole(wpNodeRef, userName); + return (userRole != null); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#getWebUserCount(org.alfresco.service.cmr.repository.NodeRef) + */ + public int getWebUserCount(NodeRef wpNodeRef) + { + return listWebUserRefs(wpNodeRef).size(); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#listWebUsers(java.lang.String) + */ + public Map listWebUsers(String wpStoreId) + { + return listWebUsers(findWebProjectNodeFromStore(wpStoreId)); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#listWebUsers(org.alfresco.service.cmr.repository.NodeRef) + */ + public Map listWebUsers(NodeRef wpNodeRef) + { + if (isContentManager(wpNodeRef)) + { + List userInfoRefs = listWebUserRefs(wpNodeRef); + + Map webUsers = new HashMap(23); + + for (ChildAssociationRef ref : userInfoRefs) + { + NodeRef userInfoRef = ref.getChildRef(); + String userName = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERNAME); + String userRole = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERROLE); + + webUsers.put(userName, userRole); + } + + return webUsers; + } + else + { + throw new AccessDeniedException("Only content managers may list users in a web project"); + } + } + + private List listWebUserRefs(NodeRef wpNodeRef) + { + return nodeService.getChildAssocs(wpNodeRef, WCMAppModel.ASSOC_WEBUSER, RegexQNamePattern.MATCH_ALL); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#getWebUserRole(java.lang.String, java.lang.String) + */ + public String getWebUserRole(String wpStoreId, String userName) + { + return getWebUserRole(findWebProjectNodeFromStore(wpStoreId), userName); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#getWebUserRole(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) + */ + public String getWebUserRole(NodeRef wpNodeRef, String userName) + { + long start = System.currentTimeMillis(); + String userRole = null; + + if (! isWebProject(wpNodeRef)) + { + logger.warn(wpNodeRef + " is not a web project"); + return null; + } + + if (authorityService.isAdminAuthority(userName)) + { + // fake the Content Manager role for an admin user + userRole = WCMUtil.ROLE_CONTENT_MANAGER; + } + else + { + StringBuilder query = new StringBuilder(128); + query.append("+PARENT:\"").append(wpNodeRef).append("\" "); + query.append("+TYPE:\"").append(WCMAppModel.TYPE_WEBUSER).append("\" "); + query.append("+@").append(NamespaceService.WCMAPP_MODEL_PREFIX).append("\\:username:\""); + query.append(userName); + query.append("\""); + + ResultSet resultSet = searchService.query( + WEBPROJECT_STORE, + SearchService.LANGUAGE_LUCENE, + query.toString()); + List nodes = resultSet.getNodeRefs(); + + if (nodes.size() == 1) + { + userRole = (String)nodeService.getProperty(nodes.get(0), WCMAppModel.PROP_WEBUSERROLE); + } + else if (nodes.size() == 0) + { + if (logger.isTraceEnabled()) + { + logger.trace("getWebProjectUserRole: user role not found for " + userName); + } + } + else + { + logger.warn("getWebProjectUserRole: more than one user role found for " + userName); + } + } + + if (logger.isTraceEnabled()) + { + logger.trace("getWebProjectUserRole: "+userName+" "+userRole+" in "+(System.currentTimeMillis()-start)+" ms"); + } + + return userRole; + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#findWebProjectNodeFromPath(java.lang.String) + */ + public NodeRef findWebProjectNodeFromPath(String absoluteAVMPath) + { + return findWebProjectNodeFromStore(WCMUtil.getStoreIdFromPath(absoluteAVMPath)); + } + + /*(non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#findWebProjectNodeFromStore(java.lang.String) + */ + public NodeRef findWebProjectNodeFromStore(String wpStoreId) + { + ParameterCheck.mandatoryString("wpStoreId", wpStoreId); + + if (wpStoreId.indexOf(WCMUtil.STORE_SEPARATOR) != -1) + { + throw new AlfrescoRuntimeException("Unexpected web project store id '"+wpStoreId+"' - should not contain '"+WCMUtil.STORE_SEPARATOR+"'"); + } + + if (wpStoreId.indexOf(":") != -1) + { + throw new AlfrescoRuntimeException("Unexpected web project store id '"+wpStoreId+"' - should not contain ':'"); + } + + // construct the query + String path = WCMUtil.getWebProjectsPath() + "/*"; + String query = "PATH:\"/" + path + "\" AND @wca\\:avmstore:\"" + wpStoreId + "\""; + + NodeRef webProjectNode = null; + ResultSet results = null; + try + { + // execute the query + results = searchService.query(WEBPROJECT_STORE, SearchService.LANGUAGE_LUCENE, query); + + // WCM-810: + // the 'avmstore' property was not defined as an identifier in the model (before 2.2) + // which means it may get tokenised which in turn means that 'test' and 'test-site' + // would get returned by the query above even though it's an exact match query, + // we therefore need to go through the results and check names if there is more + // than one result although this shouldn't happen anymore as the + // AVMStorePropertyTokenisationPatch will have reindexed the wca:avmstore property + if (results.length() == 1) + { + webProjectNode = results.getNodeRef(0); + } + else if (results.length() > 1) + { + for (NodeRef node : results.getNodeRefs()) + { + String nodeStoreName = (String)nodeService.getProperty(node, WCMAppModel.PROP_AVMSTORE); + if (nodeStoreName.equals(wpStoreId)) + { + webProjectNode = node; + break; + } + } + } + } + finally + { + if (results != null) + { + results.close(); + } + } + + return webProjectNode; + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#inviteWebUsersGroups(java.lang.String, java.util.Map) + */ + public void inviteWebUsersGroups(String wpStoreId, Map userGroupRoles) + { + inviteWebUsersGroups(findWebProjectNodeFromStore(wpStoreId), userGroupRoles); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#inviteWebUsers(org.alfresco.service.cmr.repository.NodeRef, java.util.Map) + */ + public void inviteWebUsersGroups(NodeRef wpNodeRef, Map userGroupRoles) + { + if (! isContentManager(wpNodeRef)) + { + throw new AccessDeniedException("Only content managers may invite web users"); + } + + WebProjectInfo wpInfo = getWebProject(wpNodeRef); + String wpStoreId = wpInfo.getStoreId(); + + // create a sandbox for each user appropriately with permissions based on role + // build a list of managers who will have full permissions on ALL staging areas + List managers = new ArrayList(4); + Set existingUsers = new HashSet(8); + + // website already exists - we are only adding to the existing sandboxes + // so retrieve the list of managers from the existing users and the selected invitees + for (Map.Entry userRole : userGroupRoles.entrySet()) + { + String authority = userRole.getKey(); + String role = userRole.getValue(); + + for (String userAuth : findNestedUserAuthorities(authority)) + { + if (WCMUtil.ROLE_CONTENT_MANAGER.equals(role)) + { + managers.add(userAuth); + } + } + } + + Map existingUserRoles = listWebUsers(wpNodeRef); + for (Map.Entry userRole : existingUserRoles.entrySet()) + { + String username = userRole.getKey(); + String userrole = userRole.getValue(); + + if (WCMUtil.ROLE_CONTENT_MANAGER.equals(userrole) && managers.contains(username) == false) + { + managers.add(username); + } + + // add each existing user to the exclude this - we cannot add them more than once! + existingUsers.add(username); + } + + // build the sandboxes now we have the manager list and complete user list + // and create an association to a node to represent each invited user + + List sandboxInfoList = new LinkedList(); + + int invitedCount = 0; + boolean managersUpdateRequired = false; + + for (Map.Entry userRole : userGroupRoles.entrySet()) + { + String authority = userRole.getKey(); + String role = userRole.getValue(); + + for (String userAuth : findNestedUserAuthorities(authority)) + { + // create the sandbox if the invited user does not already have one + if (existingUsers.contains(userAuth) == false) + { + SandboxInfo info = sandboxFactory.createUserSandbox(wpStoreId, managers, userAuth, role); + sandboxInfoList.add(info); + + sandboxFactory.addStagingAreaUser(wpStoreId, userAuth, role); + + // create an app:webuser instance for each authority and assoc to the web project node + createWebUser(wpNodeRef, userAuth, role); + + // if this new user is a manager, we'll need to update the manager permissions applied + // to each existing user sandbox - to ensure that new managers have access to them + managersUpdateRequired |= (WCMUtil.ROLE_CONTENT_MANAGER.equals(role)); + + invitedCount++; + } + else + { + logger.warn("User '"+userAuth+"' already invited to web project: "+wpNodeRef+"(store id: "+wpStoreId+")"); + } + } + } + + if (managersUpdateRequired == true) + { + // walk existing sandboxes and reapply manager permissions to include any new manager users + for (Map.Entry userRole : existingUserRoles.entrySet()) + { + String username = userRole.getKey(); + if (existingUsers.contains(username)) + { + // only need to modify the sandboxes we haven't just created + sandboxFactory.updateSandboxManagers(wpStoreId, managers, username); + } + } + sandboxFactory.updateStagingAreaManagers(wpStoreId, wpNodeRef, managers); + } + + // get permissions and roles for a web project folder type + Set perms = permissionService.getSettablePermissions(WCMAppModel.TYPE_AVMWEBFOLDER); + + // set permissions for each user + for (Map.Entry userRole : userGroupRoles.entrySet()) + { + String authority = userRole.getKey(); + String role = userRole.getValue(); + + for (String permission : perms) + { + if (role.equals(permission)) + { + permissionService.setPermission(wpNodeRef, + authority, + permission, + true); + break; + } + } + } + + // Bind the post-commit transaction listener with data required for virtualization server notification + InviteWebUsersTransactionListener tl = new InviteWebUsersTransactionListener(sandboxInfoList, listWebApps(wpNodeRef)); + AlfrescoTransactionSupport.bindListener(tl); + + if (logger.isInfoEnabled()) + { + logger.info("Invited "+invitedCount+" web users (store id: "+wpStoreId+")"); + } + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#inviteWebUser(java.lang.String, java.lang.String, java.lang.String) + */ + public void inviteWebUser(String wpStoreId, String userAuth, String role) + { + inviteWebUser(findWebProjectNodeFromStore(wpStoreId), userAuth, role); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#inviteWebUser(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String) + */ + public void inviteWebUser(NodeRef wpNodeRef, String userAuth, String role) + { + if (! isContentManager(wpNodeRef)) + { + throw new AccessDeniedException("Only content managers may invite web user"); + } + + WebProjectInfo wpInfo = getWebProject(wpNodeRef); + String wpStoreId = wpInfo.getStoreId(); + + boolean existingUser = false; + + // create a sandbox for the user with permissions based on role + // build a list of managers who will have full permissions on ALL staging areas + List managers = new ArrayList(4); + + // retrieve the list of managers from the existing users + Map existingUserRoles = listWebUsers(wpNodeRef); + for (Map.Entry userRole : existingUserRoles.entrySet()) + { + String username = userRole.getKey(); + String userrole = userRole.getValue(); + + if (WCMUtil.ROLE_CONTENT_MANAGER.equals(userrole) && managers.contains(username) == false) + { + managers.add(username); + } + + if (username.equals(userAuth)) + { + existingUser = true; + break; + } + } + + if (existingUser) + { + logger.warn("User '"+userAuth+"' already invited to web project: "+wpNodeRef+" (store id: "+wpStoreId+")"); + return; + } + else + { + // if this new user is a manager, we'll need to update the manager permissions applied + // to each existing user sandbox - to ensure that new user has access to them + if (WCMUtil.ROLE_CONTENT_MANAGER.equals(role)) + { + managers.add(userAuth); + + // walk existing sandboxes and reapply manager permissions to include new manager user + for (Map.Entry userRole : existingUserRoles.entrySet()) + { + String username = userRole.getKey(); + sandboxFactory.updateSandboxManagers(wpStoreId, managers, username); + } + sandboxFactory.updateStagingAreaManagers(wpStoreId, wpNodeRef, managers); + } + + // build the user sandboxes now we have the manager list + // and create an association to a node to represent invited user + + List sandboxInfoList = new LinkedList(); + + SandboxInfo info = sandboxFactory.createUserSandbox(wpStoreId, managers, userAuth, role); + sandboxInfoList.add(info); + + sandboxFactory.addStagingAreaUser(wpStoreId, userAuth, role); + + // create an app:webuser instance for the user and assoc to the web project node + createWebUser(wpNodeRef, userAuth, role); + + // get permissions and roles for a web project folder type + Set perms = permissionService.getSettablePermissions(WCMAppModel.TYPE_AVMWEBFOLDER); + + // set permissions for the user + for (String permission : perms) + { + if (role.equals(permission)) + { + permissionService.setPermission(wpNodeRef, + userAuth, + permission, + true); + break; + } + } + + // Bind the post-commit transaction listener with data required for virtualization server notification + InviteWebUsersTransactionListener tl = new InviteWebUsersTransactionListener(sandboxInfoList, listWebApps(wpNodeRef)); + AlfrescoTransactionSupport.bindListener(tl); + + if (logger.isInfoEnabled()) + { + logger.info("Invited web user: "+userAuth+" (store id: "+wpStoreId+")"); + } + } + } + + private void createWebUser(NodeRef wpNodeRef, String userName, String userRole) + { + // create an app:webuser instance for the user and assoc to the web project node + Map props = new HashMap(2, 1.0f); + props.put(WCMAppModel.PROP_WEBUSERNAME, userName); + props.put(WCMAppModel.PROP_WEBUSERROLE, userRole); + nodeService.createNode(wpNodeRef, + WCMAppModel.ASSOC_WEBUSER, + WCMAppModel.ASSOC_WEBUSER, + WCMAppModel.TYPE_WEBUSER, + props); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#uninviteWebUser(java.lang.String, java.lang.String) + */ + public void uninviteWebUser(String wpStoreId, String userAuth) + { + uninviteWebUser(findWebProjectNodeFromStore(wpStoreId), userAuth); + } + + /* (non-Javadoc) + * @see org.alfresco.wcm.webproject.WebProjectService#uninviteWebUser(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) + */ + public void uninviteWebUser(NodeRef wpNodeRef, String userAuth) + { + if (! isContentManager(wpNodeRef)) + { + throw new AccessDeniedException("Only content managers may uninvite web user '"+userAuth+"' from web project: "+wpNodeRef); + } + + ParameterCheck.mandatory("wpNodeRef", wpNodeRef); + ParameterCheck.mandatoryString("userAuth", userAuth); + + WebProjectInfo wpInfo = getWebProject(wpNodeRef); + String wpStoreId = wpInfo.getStoreId(); + String userMainStore = WCMUtil.buildUserMainStoreName(wpStoreId, userAuth); + + // remove the store reference from the website folder meta-data + List userInfoRefs = listWebUserRefs(wpNodeRef); + + // retrieve the list of managers from the existing users + List managers = new ArrayList(4); + for (ChildAssociationRef ref : userInfoRefs) + { + NodeRef userInfoRef = ref.getChildRef(); + String username = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERNAME); + String userrole = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERROLE); + + if (WCMUtil.ROLE_CONTENT_MANAGER.equals(userrole) && managers.contains(username) == false) + { + managers.add(username); + } + } + + for (ChildAssociationRef ref : userInfoRefs) + { + NodeRef userInfoRef = ref.getChildRef(); + String user = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERNAME); + + if (userAuth.equals(user)) + { + // found the sandbox to remove + String path = WCMUtil.buildSandboxRootPath(userMainStore); + + // Notify virtualisation server about removing this sandbox. + // + // Implementation note: + // + // Because the removal of virtual webapps in the + // virtualization server is recursive, it only + // needs to be given the name of the main store. + // + // This notification must occur *prior* to purging content + // within the AVM because the virtualization server must list + // the avm_webapps dir in each store to discover which + // virtual webapps must be unloaded. The virtualization + // server traverses the sandbox's stores in most-to-least + // dependent order, so clients don't have to worry about + // accessing a preview layer whose main layer has been torn + // out from under it. + + WCMUtil.removeAllVServerWebapps(virtServerRegistry, path, true); + + // TODO: Use the .sandbox-id. property to delete all sandboxes, + // rather than assume a sandbox always had a single preview + // layer attached. + + // purge the user main sandbox store from the system + avmService.purgeStore(userMainStore); + + // remove any locks this user may have + avmLockingService.removeStoreLocks(userMainStore); + + // purge the user preview sandbox store from the system + String userPreviewStore = WCMUtil.buildUserPreviewStoreName(wpStoreId, userAuth); + avmService.purgeStore(userPreviewStore); + + // remove any locks this user may have + avmLockingService.removeStoreLocks(userPreviewStore); + + // remove the association to this web project user meta-data + nodeService.removeChild(wpNodeRef, ref.getChildRef()); + + // remove permission for the user (also fixes ETWOONE-338 - also need to ensure that last content manager does not uninvite themselves) + permissionService.clearPermission(wpNodeRef, userAuth); + + if (logger.isInfoEnabled()) + { + logger.info("Uninvited web user: "+userAuth+" (store id: "+wpStoreId+")"); + } + + break; // for loop + } + } + } + + /** + * Find all nested user authorities contained with an authority + * + * @param authority The authority to search, USER authorities are returned immediately, GROUP authorites + * are recursively scanned for contained USER authorities. + * + * @return a Set of USER authorities + */ + private Set findNestedUserAuthorities(String authority) + { + Set users; + + AuthorityType authType = AuthorityType.getAuthorityType(authority); + if (authType.equals(AuthorityType.USER)) + { + users = new HashSet(1, 1.0f); + if (personService.personExists(authority) == true) + { + users.add(authority); + } + } + else if (authType.equals(AuthorityType.GROUP)) + { + // walk each member of the group + users = authorityService.getContainedAuthorities(AuthorityType.USER, authority, false); + for (String userAuth : users) + { + if (personService.personExists(userAuth) == false) + { + users.remove(authType); + } + } + } + else + { + users = Collections.emptySet(); + } + + return users; + } + + /** + * Transaction listener - invoked after commit + */ + private class CreateWebProjectTransactionListener extends TransactionListenerAdapter + { + private String wpStoreId; + + public CreateWebProjectTransactionListener(String wpStoreId) + { + this.wpStoreId = wpStoreId; + } + + /** + * @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterCommit() + */ + @Override + public void afterCommit() + { + // post-commit + if (wpStoreId != null) + { + // update the virtualisation server with the default ROOT webapp path + // performed after the main txn has committed successfully + String newStoreName = WCMUtil.buildStagingStoreName(wpStoreId); + + String path = WCMUtil.buildStoreWebappPath(newStoreName, WCMUtil.DIR_ROOT); + + WCMUtil.updateVServerWebapp(virtServerRegistry, path, true); + } + } + } + + /** + * Invite Web Users Transaction listener - invoked after commit + */ + private class InviteWebUsersTransactionListener extends TransactionListenerAdapter + { + private List sandboxInfoList; + private List webAppNames; + + public InviteWebUsersTransactionListener(List sandboxInfoList, List webAppNames) + { + this.sandboxInfoList = sandboxInfoList; + this.webAppNames = webAppNames; + } + + /** + * @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterCommit() + */ + @Override + public void afterCommit() + { + // Handle notification to the virtualization server + // (this needs to occur after the sandboxes are created in the main txn) + + // reload virtualisation server for webapp(s) in this web project + for (SandboxInfo sandboxInfo : this.sandboxInfoList) + { + String newlyInvitedStoreName = WCMUtil.buildStagingStoreName(sandboxInfo.getMainStoreName()); + + for (String webAppName : webAppNames) + { + String path = WCMUtil.buildStoreWebappPath(newlyInvitedStoreName, webAppName); + WCMUtil.updateVServerWebapp(virtServerRegistry, path, true); + } + } + } + } +} diff --git a/source/java/org/alfresco/wcm/webproject/WebProjectServiceImplTest.java b/source/java/org/alfresco/wcm/webproject/WebProjectServiceImplTest.java new file mode 100644 index 0000000000..4e331d026b --- /dev/null +++ b/source/java/org/alfresco/wcm/webproject/WebProjectServiceImplTest.java @@ -0,0 +1,1102 @@ +/* + * 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.wcm.webproject; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import junit.framework.TestCase; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.service.cmr.avm.AVMExistsException; +import org.alfresco.service.cmr.avm.AVMNotFoundException; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.cmr.security.AuthorityType; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.util.ApplicationContextHelper; +import org.alfresco.util.PropertyMap; +import org.alfresco.wcm.util.WCMUtil; +import org.springframework.context.ApplicationContext; + +/** + * Web Project Service implementation unit test + * + * @author janv + */ +public class WebProjectServiceImplTest extends TestCase +{ + private static final ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); + + // + // test data + // + + private static final String TEST_RUN = ""+System.currentTimeMillis(); + private static final boolean CLEAN = true; // cleanup during teardown + + // base web project dns / name + private static final String TEST_WEBPROJ_DNS = "testWebProjDNS-"+TEST_RUN; + private static final String TEST_WEBPROJ_NAME = "test Web Project Display Name - "+TEST_RUN; + + // web app names + private static final String TEST_WEBAPP = "myWebApp"; + + private static final String TEST_WEBAPP1 = TEST_WEBAPP+"-AppOne"; + private static final String TEST_WEBAPP2 = TEST_WEBAPP+"-AppTwo"; + private static final String TEST_WEBAPP3 = TEST_WEBAPP+"-AppThree"; + + // general + private static final String TEST_TITLE = "This is my title"; + private static final String TEST_DESCRIPTION = "This is my description"; + private static final String TEST_DEFAULT_WEBAPP = "defWebApp"; + private static final boolean TEST_USE_AS_TEMPLATE = true; + + private static final String USER_ADMIN = "admin"; + + private static final String TEST_USER = "testWebProjUser-"+TEST_RUN; + private static final String TEST_GROUP = "testWebProjGroup-"+TEST_RUN; + + private static final String USER_ONE = TEST_USER+"-One"; + private static final String USER_TWO = TEST_USER+"-Two"; + private static final String USER_THREE = TEST_USER+"-Three"; + private static final String USER_FOUR = TEST_USER+"-Four"; + private static final String USER_FIVE = TEST_USER+"-Five"; + + private static final String GROUP_ONE = TEST_GROUP+"-One"; + + private static final int SCALE_USERS = 5; + private static final int SCALE_WEBPROJECTS = 5; + private static final int SCALE_WEBAPPS = 5; + + + // + // services + // + + private WebProjectService wpService; + private AuthenticationService authenticationService; + private PersonService personService; + private FileFolderService fileFolderService; + private AuthorityService authorityService; + + + @Override + protected void setUp() throws Exception + { + // Get the required services + wpService = (WebProjectService)ctx.getBean("WebProjectService"); + authenticationService = (AuthenticationService)ctx.getBean("AuthenticationService"); + personService = (PersonService)ctx.getBean("PersonService"); + fileFolderService = (FileFolderService)ctx.getBean("FileFolderService"); + authorityService = (AuthorityService)ctx.getBean("AuthorityService"); + + // By default run as Admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + createUser(USER_ONE); + createUser(USER_TWO); + createUser(USER_THREE); + createUser(USER_FOUR); + createUser(USER_FIVE); + + Set userNames = new HashSet(2); + userNames.add(USER_ONE); + userNames.add(USER_TWO); + + createSimpleGroup(GROUP_ONE, userNames); + } + + @Override + protected void tearDown() throws Exception + { + if (CLEAN) + { + // Switch back to Admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + List webProjects = wpService.listWebProjects(); + for (WebProjectInfo wpInfo : webProjects) + { + if (wpInfo.getStoreId().startsWith(TEST_WEBPROJ_DNS)) + { + wpService.deleteWebProject(wpInfo.getNodeRef()); + } + } + + deleteGroup(GROUP_ONE); + + deleteUser(USER_ONE); + deleteUser(USER_TWO); + deleteUser(USER_THREE); + deleteUser(USER_FOUR); + deleteUser(USER_FIVE); + + NodeRef wpRoot = wpService.getWebProjectsRoot(); + List list = fileFolderService.list(wpRoot); + for (FileInfo fileOrFolder : list) + { + if (fileOrFolder.getName().contains(TEST_RUN)) + { + fileFolderService.delete(fileOrFolder.getNodeRef()); + } + } + } + + AuthenticationUtil.clearCurrentSecurityContext(); + super.tearDown(); + } + + private void createUser(String userName) + { + if (authenticationService.authenticationExists(userName) == false) + { + authenticationService.createAuthentication(userName, "PWD".toCharArray()); + + PropertyMap ppOne = new PropertyMap(4); + ppOne.put(ContentModel.PROP_USERNAME, userName); + ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName"); + ppOne.put(ContentModel.PROP_LASTNAME, "lastName"); + ppOne.put(ContentModel.PROP_EMAIL, "email@email.com"); + ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); + + personService.createPerson(ppOne); + } + } + + private void createSimpleGroup(String shortName, Set userNames) + { + String groupName = authorityService.getName(AuthorityType.GROUP, shortName); + if (authorityService.authorityExists(groupName) == false) + { + authorityService.createAuthority(AuthorityType.GROUP, null, shortName); + + for (String userName : userNames) + { + authorityService.addAuthority(groupName, userName); + } + } + } + + private void deleteUser(String userName) + { + if (authenticationService.authenticationExists(userName) == true) + { + personService.deletePerson(userName); + authenticationService.deleteAuthentication(userName); + } + } + + private void deleteGroup(String shortName) + { + String groupName = authorityService.getName(AuthorityType.GROUP, shortName); + if (authorityService.authorityExists(groupName) == true) + { + authorityService.deleteAuthority(groupName); + } + } + + public void testCreateWebProjectSimple() + { + // Create a web project + WebProjectInfo wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-simple", TEST_WEBPROJ_NAME+"-simple", TEST_TITLE, TEST_DESCRIPTION); + assertNotNull(wpInfo); + } + + public void testCreateWebProject() + { + // Create a web project + WebProjectInfo wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-create", TEST_WEBPROJ_NAME+"-create", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE, null); + checkWebProjectInfo(wpInfo, TEST_WEBPROJ_DNS+"-create", TEST_WEBPROJ_NAME+"-create", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE); + + // Mangled case + String dnsName = TEST_WEBPROJ_DNS+"some.unexpected.chars"; + String name = dnsName + " name"; + String mangledDnsName = TEST_WEBPROJ_DNS+"some-unexpected-chars"; + + wpInfo = wpService.createWebProject(dnsName, name, TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE, null); + checkWebProjectInfo(wpInfo, mangledDnsName, name, TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE); + wpInfo = wpService.getWebProject(mangledDnsName); + checkWebProjectInfo(wpInfo, mangledDnsName, name, TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE); + + // Another mangled case + dnsName = TEST_WEBPROJ_DNS+"some.moreé1í2ó3ú4Á5É6Í7Ó8Ú9"; + mangledDnsName = TEST_WEBPROJ_DNS+"some-more-1-2-3-4-5-6-7-8-9"; + + name = dnsName + " name"; + + wpInfo = wpService.createWebProject(dnsName, name, TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE, null); + checkWebProjectInfo(wpInfo, mangledDnsName, name, TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE); + wpInfo = wpService.getWebProject(mangledDnsName); + checkWebProjectInfo(wpInfo, mangledDnsName, name, TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE); + + // Invalid dns name (with '--') + dnsName = "my--dns"; + name = dnsName + " name"; + try + { + // Try to create invalid web project with invalid dns name (-ve test) + wpInfo = wpService.createWebProject(dnsName, name, TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE, null); + fail("Shouldn't be able to create web project with '--'"); + } + catch (AlfrescoRuntimeException exception) + { + // Expected + } + + // Invalid mangled case + dnsName = "!£$%^&*()_+=-[]{}"; // generates mangled dns name = x---------------x + name = dnsName + " name"; + try + { + // Try to create invalid web project (-ve test) + wpInfo = wpService.createWebProject(dnsName, name, TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE, null); + fail("Shouldn't be able to create web project with '--'"); + } + catch (AlfrescoRuntimeException exception) + { + // Expected + } + + // Duplicate web project dns/store name + try + { + // Try to create duplicate web project dns/store (-ve test) + wpService.createWebProject(TEST_WEBPROJ_DNS+"-create", TEST_WEBPROJ_NAME+"-x", TEST_TITLE+"x", TEST_DESCRIPTION+"x", TEST_DEFAULT_WEBAPP+"x", TEST_USE_AS_TEMPLATE, null); + fail("Shouldn't allow duplicate web project dns/store name"); + } + catch (AlfrescoRuntimeException exception) + { + // Expected + } + + // Duplicate web project folder/name + try + { + // Try to create duplicate web project folder/name (-ve test) + wpService.createWebProject(TEST_WEBPROJ_DNS+"x", TEST_WEBPROJ_NAME+"-create", TEST_TITLE+"x", TEST_DESCRIPTION+"x", TEST_DEFAULT_WEBAPP+"x", TEST_USE_AS_TEMPLATE, null); + fail("Shouldn't allow duplicate web project folder/name"); + } + catch (DuplicateChildNodeNameException exception) + { + // Expected + } + } + + private void checkWebProjectInfo(WebProjectInfo wpInfo, String expectedStoreId, String expectedName, String expectedTitle, + String expectedDescription, String expectedDefaultWebApp, boolean expectedUseAsTemplate) + { + assertNotNull(wpInfo); + assertEquals(expectedStoreId, wpInfo.getStoreId()); + assertEquals(expectedName, wpInfo.getName()); + assertEquals(expectedTitle, wpInfo.getTitle()); + assertEquals(expectedDescription, wpInfo.getDescription()); + assertEquals(expectedDefaultWebApp, wpInfo.getDefaultWebApp()); + assertEquals(expectedUseAsTemplate, wpInfo.isTemplate()); + assertNotNull(wpInfo.getNodeRef()); + } + + public void testListWebProjects() throws Exception + { + // As admin, check for existing projects + List webProjects = wpService.listWebProjects(); + assertNotNull(webProjects); + int cnt = webProjects.size(); + + // Create some web projects + wpService.createWebProject(TEST_WEBPROJ_DNS+"-list1", TEST_WEBPROJ_NAME+" list1", TEST_TITLE, TEST_DESCRIPTION); + wpService.createWebProject(TEST_WEBPROJ_DNS+"-list2", TEST_WEBPROJ_NAME+" list2", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, true, null); + wpService.createWebProject(TEST_WEBPROJ_DNS+"-list3", TEST_WEBPROJ_NAME+" list3", TEST_TITLE, TEST_DESCRIPTION); + wpService.createWebProject(TEST_WEBPROJ_DNS+"-list4", TEST_WEBPROJ_NAME+" list4", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, true, null); + + // Get all the web projects for the current user + webProjects = wpService.listWebProjects(); + assertNotNull(webProjects); + assertEquals((cnt + 4), webProjects.size()); + + // Do detailed check of the web project info objects + for (WebProjectInfo wpInfo : webProjects) + { + String wpStoreId = wpInfo.getStoreId(); + if (wpStoreId.equals(TEST_WEBPROJ_DNS+"-list1") == true) + { + checkWebProjectInfo(wpInfo, TEST_WEBPROJ_DNS+"-list1", TEST_WEBPROJ_NAME+" list1", TEST_TITLE, TEST_DESCRIPTION, WCMUtil.DIR_ROOT, false); + } + else if (wpStoreId.equals(TEST_WEBPROJ_DNS+"-list2") == true) + { + checkWebProjectInfo(wpInfo, TEST_WEBPROJ_DNS+"-list2", TEST_WEBPROJ_NAME+" list2", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, true); + } + else if (wpStoreId.equals(TEST_WEBPROJ_DNS+"-list3") == true) + { + checkWebProjectInfo(wpInfo, TEST_WEBPROJ_DNS+"-list3", TEST_WEBPROJ_NAME+" list3", TEST_TITLE, TEST_DESCRIPTION, WCMUtil.DIR_ROOT, false); + } + else if (wpStoreId.equals(TEST_WEBPROJ_DNS+"-list4") == true) + { + checkWebProjectInfo(wpInfo, TEST_WEBPROJ_DNS+"-list4", TEST_WEBPROJ_NAME+" list4", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, true); + } + else + { + //fail("The web project store id " + wpStoreId + " is not recognised"); + System.out.println("The web project store id " + wpStoreId + " is not recognised"); + } + } + + // Switch to USER_ONE + AuthenticationUtil.setCurrentUser(USER_ONE); + + // Get all the web projects for the current user + webProjects = wpService.listWebProjects(); + assertNotNull(webProjects); + + if (! webProjects.isEmpty()) + { + for (WebProjectInfo wpInfo : webProjects) + { + String wpStoreId = wpInfo.getStoreId(); + if (wpStoreId.equals(TEST_WEBPROJ_DNS+"-list-1") == true) + { + fail("User should not see "+TEST_WEBPROJ_DNS+"-list-1"); + } + else if (wpStoreId.equals(TEST_WEBPROJ_DNS+"-list-2") == true) + { + fail("User should not see "+TEST_WEBPROJ_DNS+"-list-2"); + } + else if (wpStoreId.equals(TEST_WEBPROJ_DNS+"-list-3") == true) + { + fail("User should not see "+TEST_WEBPROJ_DNS+"-list-3"); + } + else if (wpStoreId.equals(TEST_WEBPROJ_DNS+"-list-4") == true) + { + fail("User should not see "+TEST_WEBPROJ_DNS+"-list-4"); + } + } + } + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + webProjects = wpService.listWebProjects(); + cnt = webProjects.size(); + + NodeRef wpRoot = wpService.getWebProjectsRoot(); + + fileFolderService.create(wpRoot, "a folder "+TEST_RUN, ContentModel.TYPE_FOLDER); + fileFolderService.create(wpRoot, "some content "+TEST_RUN, ContentModel.TYPE_CONTENT); + + webProjects = wpService.listWebProjects(); + assertEquals(cnt, webProjects.size()); + } + + public void testGetWebProject() + { + // Get a web project that isn't there + WebProjectInfo wpInfo = wpService.getWebProject(TEST_WEBPROJ_DNS+"-get"); + assertNull(wpInfo); + + // Create a web project + wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-get", TEST_WEBPROJ_NAME+"-get", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE, null); + + // Get the web project - test using wpStoreId + wpInfo = wpService.getWebProject(wpInfo.getStoreId()); + assertNotNull(wpInfo); + checkWebProjectInfo(wpInfo, TEST_WEBPROJ_DNS+"-get", TEST_WEBPROJ_NAME+"-get", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE); + + // Get the web project - test using wpStoreNodeRef + wpInfo = wpService.getWebProject(wpInfo.getNodeRef()); + assertNotNull(wpInfo); + checkWebProjectInfo(wpInfo, TEST_WEBPROJ_DNS+"-get", TEST_WEBPROJ_NAME+"-get", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, TEST_USE_AS_TEMPLATE); + } + + public void testUpdateWebProject() + { + WebProjectInfo wpInfo = new WebProjectInfoImpl(TEST_WEBPROJ_DNS+"-update", TEST_WEBPROJ_NAME+"-update", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, false, null); + + try + { + // Try to update a web project that isn't there (-ve test) + wpService.updateWebProject(wpInfo); + fail("Shouldn't be able to update a web project that does not exist"); + } + catch (AlfrescoRuntimeException exception) + { + // Expected + } + + // Create a test web project + wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-update", TEST_WEBPROJ_NAME+"-update", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, true, null); + + wpInfo.setName("changedName"+TEST_RUN); + wpInfo.setTitle("changedTitle"); + wpInfo.setDescription("changedDescription"); + wpInfo.setIsTemplate(false); + + // Update the details of the web project + wpService.updateWebProject(wpInfo); + wpInfo = wpService.getWebProject(wpInfo.getStoreId()); + checkWebProjectInfo(wpInfo, TEST_WEBPROJ_DNS+"-update", "changedName"+TEST_RUN, "changedTitle", "changedDescription", TEST_DEFAULT_WEBAPP, false); + } + + public void testDeleteWebProject() + { + // Create a test web project + WebProjectInfo wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-delete", TEST_WEBPROJ_NAME+"-delete", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, true, null); + String wpStoreId = wpInfo.getStoreId(); + assertNotNull(wpService.getWebProject(wpStoreId)); + + // Switch to USER_ONE + AuthenticationUtil.setCurrentUser(USER_ONE); + + try + { + // Try to delete the web project as a non-content-manager (-ve test) + wpService.deleteWebProject(wpStoreId); + fail("Shouldn't be able to delete the web project since not a content manager"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Switch user to System + AuthenticationUtil.setSystemUserAsCurrentUser(); + + try + { + // Try to delete the web project as a non-content-manager (such as System) (-ve test) + wpService.deleteWebProject(wpStoreId); + fail("Shouldn't be able to delete the web project since not a content manager"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + // Delete the web project + wpService.deleteWebProject(wpStoreId); + assertNull(wpService.getWebProject(wpStoreId)); + + try + { + // Try to delete a web project that isn't there (-ve test) + wpService.deleteWebProject("someRandomWebProject"); + fail("Shouldn't be able to delete the web project since it does not exist (or is not visible to current user)"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Create another test web project + wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-delete2", TEST_WEBPROJ_NAME+"-delete2", TEST_TITLE, TEST_DESCRIPTION, TEST_DEFAULT_WEBAPP, true, null); + assertNotNull(wpService.getWebProject(wpInfo.getStoreId())); + + wpService.inviteWebUser(wpInfo.getNodeRef(), USER_ONE, WCMUtil.ROLE_CONTENT_MANAGER); + + // Switch to USER_TWO + AuthenticationUtil.setCurrentUser(USER_TWO); + + try + { + // Try to delete a web project that isn't there (-ve test) + wpService.deleteWebProject(TEST_WEBPROJ_DNS+"-delete2"); + fail("Shouldn't be able to delete the web project since it does not exist (or is not visible to current user)"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Switch to USER_ONE + AuthenticationUtil.setCurrentUser(USER_ONE); + + // Delete the web project + wpService.deleteWebProject(TEST_WEBPROJ_DNS+"-delete2"); + } + + public void testCreateWebApp() + { + // Create a web project with a default webapp + WebProjectInfo wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-createWebApp", TEST_WEBPROJ_NAME+"-createWebApp", TEST_TITLE, TEST_DESCRIPTION, TEST_WEBAPP1, TEST_USE_AS_TEMPLATE, null); + + // Switch user to System + AuthenticationUtil.setSystemUserAsCurrentUser(); + + try + { + // Try to create another webapp as a non-content-manager (such as System) (-ve test) + wpService.createWebApp(wpInfo.getStoreId(), TEST_WEBAPP2, TEST_DESCRIPTION); + fail("Shouldn't be able to create a webapp since not a content manager"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + // Create another webapp - test using wpStoreId + wpService.createWebApp(wpInfo.getStoreId(), TEST_WEBAPP2, TEST_DESCRIPTION); + + try + { + // Try to create duplicate webapp (-ve test) + wpService.createWebApp(wpInfo.getStoreId(), TEST_WEBAPP2, TEST_DESCRIPTION); + fail("Shouldn't allow duplicate webapp name"); + } + catch (AVMExistsException exception) + { + // Expected + } + + // Create another webapp - test using wpNodeRef + wpService.createWebApp(wpInfo.getNodeRef(), TEST_WEBAPP3, TEST_DESCRIPTION); + } + + public void testListWebApps() + { + try + { + // Try to list webapps (-ve test) + wpService.listWebApps(new NodeRef("dummy://dummy/dummy")); + fail("Shouldn't be able to list webapps for a non-existent web project"); + } + catch (IllegalArgumentException exception) + { + // Expected + } + + // Create a web project with default ROOT webapp + WebProjectInfo wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-listWebApps", TEST_WEBPROJ_NAME+"-listWebApps", TEST_TITLE, TEST_DESCRIPTION); + NodeRef wpNodeRef = wpInfo.getNodeRef(); + + // List web apps - test using wpStoreId + List webAppNames = wpService.listWebApps(wpInfo.getStoreId()); + assertNotNull(webAppNames); + assertEquals(1, webAppNames.size()); + assertTrue(webAppNames.contains(WCMUtil.DIR_ROOT)); + + // List web apps - test using wpNodeRef + webAppNames = wpService.listWebApps(wpNodeRef); + assertNotNull(webAppNames); + assertEquals(1, webAppNames.size()); + assertTrue(webAppNames.contains(WCMUtil.DIR_ROOT)); + + // Create some more webapps + wpService.createWebApp(wpNodeRef, TEST_WEBAPP1, TEST_DESCRIPTION); + wpService.createWebApp(wpNodeRef, TEST_WEBAPP2, TEST_DESCRIPTION); + wpService.createWebApp(wpNodeRef, TEST_WEBAPP3, TEST_DESCRIPTION); + + webAppNames = wpService.listWebApps(wpNodeRef); + assertEquals(4, webAppNames.size()); + assertTrue(webAppNames.contains(WCMUtil.DIR_ROOT)); + assertTrue(webAppNames.contains(TEST_WEBAPP1)); + assertTrue(webAppNames.contains(TEST_WEBAPP2)); + assertTrue(webAppNames.contains(TEST_WEBAPP3)); + + wpService.deleteWebApp(wpNodeRef, TEST_WEBAPP1); + wpService.deleteWebApp(wpNodeRef, TEST_WEBAPP2); + + webAppNames = wpService.listWebApps(wpNodeRef); + assertEquals(2, webAppNames.size()); + assertTrue(webAppNames.contains(WCMUtil.DIR_ROOT)); + assertTrue(webAppNames.contains(TEST_WEBAPP3)); + } + + public void testDeleteWebApp() + { + // Create a webapp + WebProjectInfo wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-deleteWebApp", TEST_WEBPROJ_NAME+"-deleteWebApp", TEST_TITLE, TEST_DESCRIPTION, TEST_WEBAPP1, TEST_USE_AS_TEMPLATE, null); + + String wpStoreId = wpInfo.getStoreId(); + NodeRef wpNodeRef = wpInfo.getNodeRef(); + + // Create a webapp + wpService.createWebApp(wpNodeRef, TEST_WEBAPP2, TEST_DESCRIPTION); + + // Create another webapp + wpService.createWebApp(wpNodeRef, TEST_WEBAPP3, TEST_DESCRIPTION); + + // Switch user to System + AuthenticationUtil.setSystemUserAsCurrentUser(); + + try + { + // Try to delete the webapp a non-content-manager (such as System) (-ve test) + wpService.deleteWebApp(wpNodeRef, TEST_WEBAPP2); + fail("Shouldn't be able to delete the webapp since not a content manager"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + try + { + // Try to delete default webapp (-ve test) + wpService.deleteWebApp(wpNodeRef, TEST_WEBAPP1); + fail("Shouldn't be able to delete the default webapp"); + } + catch (AlfrescoRuntimeException exception) + { + // Expected + } + + // Change default webapp + wpInfo = wpService.getWebProject(wpNodeRef); + wpInfo.setDefaultWebApp(TEST_WEBAPP3); + wpService.updateWebProject(wpInfo); + + // Delete non-default webapp - test using wpStoreId + wpService.deleteWebApp(wpStoreId, TEST_WEBAPP1); + + // Delete another webapp - test using wpNodeRef + wpService.deleteWebApp(wpNodeRef, TEST_WEBAPP2); + + try + { + // Try to delete last / default webapp (-ve test) + wpService.deleteWebApp(wpNodeRef, TEST_WEBAPP3); + fail("Shouldn't be able to delete the default webapp"); + } + catch (AlfrescoRuntimeException exception) + { + // Expected + } + + // TODO - Test delete of non-empty webapp + + try + { + // Try to delete a webapp that does not exist (-ve test) + wpService.deleteWebApp(wpNodeRef, "someRandomWebApp"); + fail("Shouldn't be able to delete the webapp since it does not exist"); + } + catch (AVMNotFoundException exception) + { + // Expected + } + } + + /** + * Test inviteWebUsers + */ + public void testMultiInviteAndListWebUsers() + { + // Switch to USER_ONE + AuthenticationUtil.setCurrentUser(USER_ONE); + + List webProjects = wpService.listWebProjects(); + assertNotNull(webProjects); + int userOneWebProjectCount = webProjects.size(); + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + // Create a web project + WebProjectInfo wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-inviteWebUsers", TEST_WEBPROJ_NAME+"-inviteWebUsers", TEST_TITLE, TEST_DESCRIPTION); + NodeRef wpNodeRef = wpInfo.getNodeRef(); + + assertEquals(1, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef).get(USER_ADMIN)); + + Map userGroupRoles = new HashMap(); + userGroupRoles.put(USER_ONE, WCMUtil.ROLE_CONTENT_MANAGER); + userGroupRoles.put(USER_TWO, WCMUtil.ROLE_CONTENT_PUBLISHER); + + // Invite web users - test using wpStoreId + wpService.inviteWebUsersGroups(wpInfo.getStoreId(), userGroupRoles); + + userGroupRoles = new HashMap(); + userGroupRoles.put(USER_THREE, WCMUtil.ROLE_CONTENT_REVIEWER); + + // Invite web users - test using wpNodeRef + wpService.inviteWebUsersGroups(wpNodeRef, userGroupRoles); + + assertEquals(4, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef).get(USER_ADMIN)); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef).get(USER_ONE)); + assertEquals(WCMUtil.ROLE_CONTENT_PUBLISHER, wpService.listWebUsers(wpNodeRef).get(USER_TWO)); + assertEquals(WCMUtil.ROLE_CONTENT_REVIEWER, wpService.listWebUsers(wpNodeRef).get(USER_THREE)); + + // Switch to USER_ONE (a content manager for this web project) + AuthenticationUtil.setCurrentUser(USER_ONE); + + webProjects = wpService.listWebProjects(); + assertEquals(userOneWebProjectCount+1, webProjects.size()); + + // Test newly invited content manager can invite other + userGroupRoles = new HashMap(); + userGroupRoles.put(USER_FIVE, WCMUtil.ROLE_CONTENT_CONTRIBUTOR); + + wpService.inviteWebUsersGroups(wpNodeRef, userGroupRoles); + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + // Create a web project + wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-inviteWebUsers2", TEST_WEBPROJ_NAME+"-inviteWebUsers2", TEST_TITLE, TEST_DESCRIPTION); + wpNodeRef = wpInfo.getNodeRef(); + + assertEquals(1, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef).get(USER_ADMIN)); + + userGroupRoles = new HashMap(); + + userGroupRoles.put(authorityService.getName(AuthorityType.GROUP, GROUP_ONE), WCMUtil.ROLE_CONTENT_PUBLISHER); + + // Invite group as a set of (flattened) web users - test using wpStoreId + wpService.inviteWebUsersGroups(wpInfo.getStoreId(), userGroupRoles); + + assertEquals(3, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef).get(USER_ADMIN)); + assertEquals(WCMUtil.ROLE_CONTENT_PUBLISHER, wpService.listWebUsers(wpNodeRef).get(USER_ONE)); + assertEquals(WCMUtil.ROLE_CONTENT_PUBLISHER, wpService.listWebUsers(wpNodeRef).get(USER_TWO)); + } + + /** + * Test inviteWebUser - and listWebProjects / listWebUsers + */ + public void testInviteAndListWebUsers() + { + // Switch to USER_ONE + AuthenticationUtil.setCurrentUser(USER_ONE); + + List webProjects = wpService.listWebProjects(); + assertNotNull(webProjects); + int userOneWebProjectCount = webProjects.size(); + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + // Create a web project + WebProjectInfo wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-inviteWebUser1", TEST_WEBPROJ_NAME+"-inviteWebUser1", TEST_TITLE, TEST_DESCRIPTION); + NodeRef wpNodeRef = wpInfo.getNodeRef(); + + assertEquals(1, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef).get(USER_ADMIN)); + + // Invite one web user - test using wpStoreId + wpService.inviteWebUser(wpInfo.getStoreId(), USER_ONE, WCMUtil.ROLE_CONTENT_PUBLISHER); + + // Invite one web user - test using wpNodeRef + wpService.inviteWebUser(wpNodeRef, USER_TWO, WCMUtil.ROLE_CONTENT_MANAGER); + + assertEquals(3, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(WCMUtil.ROLE_CONTENT_PUBLISHER, wpService.listWebUsers(wpNodeRef).get(USER_ONE)); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef).get(USER_TWO)); + + // Create another web project + wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-inviteWebUser2", TEST_WEBPROJ_NAME+"-inviteWebUser2", TEST_TITLE, TEST_DESCRIPTION); + NodeRef wpNodeRef2 = wpInfo.getNodeRef(); + + assertEquals(1, wpService.listWebUsers(wpNodeRef2).size()); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef2).get(USER_ADMIN)); + + wpService.inviteWebUser(wpNodeRef2, USER_TWO, WCMUtil.ROLE_CONTENT_PUBLISHER); + wpService.inviteWebUser(wpNodeRef2, USER_ONE, WCMUtil.ROLE_CONTENT_MANAGER); + + assertEquals(3, wpService.listWebUsers(wpNodeRef2).size()); + assertEquals(WCMUtil.ROLE_CONTENT_PUBLISHER, wpService.listWebUsers(wpNodeRef2).get(USER_TWO)); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef2).get(USER_ONE)); + + // Switch to USER_ONE + AuthenticationUtil.setCurrentUser(USER_ONE); + + webProjects = wpService.listWebProjects(); + assertEquals(userOneWebProjectCount+2, webProjects.size()); + + // Switch to USER_TWO + AuthenticationUtil.setCurrentUser(USER_TWO); + + try + { + // Try to invite web user as a non-content-manager (-ve test) + wpService.inviteWebUser(wpNodeRef2, USER_THREE, WCMUtil.ROLE_CONTENT_REVIEWER); + fail("Shouldn't be able to invite web user since not a content manager"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Switch user to System + AuthenticationUtil.setSystemUserAsCurrentUser(); + + try + { + // Try to invite web user as a non-content-manager (such as System) (-ve test) + wpService.inviteWebUser(wpNodeRef2, USER_THREE, WCMUtil.ROLE_CONTENT_REVIEWER); + fail("Shouldn't be able to invite web user since not a content manager"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Test newly invited content manager can invite other + + // Switch to USER_ONE + AuthenticationUtil.setCurrentUser(USER_ONE); + + // Invite web user + wpService.inviteWebUser(wpNodeRef2, USER_THREE, WCMUtil.ROLE_CONTENT_REVIEWER); + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + assertEquals(4, wpService.listWebUsers(wpNodeRef2).size()); + assertEquals(WCMUtil.ROLE_CONTENT_REVIEWER, wpService.listWebUsers(wpNodeRef2).get(USER_THREE)); + } + + /** + * Test uninviteWebUser - and listWebProjects / listWebUsers + */ + public void testUninviteAndListWebUsers() + { + // Switch to USER_FOUR + AuthenticationUtil.setCurrentUser(USER_FOUR); + + List webProjects = wpService.listWebProjects(); + assertNotNull(webProjects); + assertEquals(0, webProjects.size()); + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + // Create a web project + WebProjectInfo wpInfo = wpService.createWebProject(TEST_WEBPROJ_DNS+"-uninviteWebUser", TEST_WEBPROJ_NAME+"-uninviteWebUser", TEST_TITLE, TEST_DESCRIPTION); + NodeRef wpNodeRef = wpInfo.getNodeRef(); + + assertEquals(1, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef).get(USER_ADMIN)); + + wpService.inviteWebUser(wpNodeRef, USER_FOUR, WCMUtil.ROLE_CONTENT_CONTRIBUTOR); + + assertEquals(2, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(WCMUtil.ROLE_CONTENT_CONTRIBUTOR, wpService.listWebUsers(wpNodeRef).get(USER_FOUR)); + + wpService.inviteWebUser(wpNodeRef, USER_ONE, WCMUtil.ROLE_CONTENT_MANAGER); + + assertEquals(3, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef).get(USER_ONE)); + + // Switch to USER_FOUR + AuthenticationUtil.setCurrentUser(USER_FOUR); + + webProjects = wpService.listWebProjects(); + assertEquals(1, webProjects.size()); + + // Switch to USER_TWO + AuthenticationUtil.setCurrentUser(USER_TWO); + + try + { + // Try to uninvite web user as a non-content-manager (-ve test) + wpService.uninviteWebUser(wpNodeRef, USER_FOUR); + fail("Shouldn't be able to uninvite web user since not a content manager"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Switch user to System + AuthenticationUtil.setSystemUserAsCurrentUser(); + + try + { + // Try to uninvite web user as a non-content-manager (such as System) (-ve test) + wpService.uninviteWebUser(wpNodeRef, USER_FOUR); + fail("Shouldn't be able to uninvite web user since not a content manager"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + // Uninvite web user - test using wpStoreId + wpService.uninviteWebUser(wpInfo.getStoreId(), USER_FOUR); + + assertEquals(2, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(null, wpService.listWebUsers(wpNodeRef).get(USER_FOUR)); + + // Switch to USER_FOUR + AuthenticationUtil.setCurrentUser(USER_FOUR); + + webProjects = wpService.listWebProjects(); + assertEquals(0, webProjects.size()); + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + // Content manager can uninvite themself + // Uninvite web user - test using wpNodeRef + wpService.uninviteWebUser(wpNodeRef, USER_ADMIN); + + assertEquals(1, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(null, wpService.listWebUsers(wpNodeRef).get(USER_ADMIN)); + + // Switch to USER_ONE + AuthenticationUtil.setCurrentUser(USER_ONE); + + assertEquals(1, wpService.listWebUsers(wpNodeRef).size()); + assertEquals(WCMUtil.ROLE_CONTENT_MANAGER, wpService.listWebUsers(wpNodeRef).get(USER_ONE)); + + // Delete user (in this case, last invited content manager) + wpService.uninviteWebUser(wpNodeRef, USER_ONE); + + try + { + // Try to delete the web project as a non-content-manager (-ve test) + wpService.deleteWebProject(wpNodeRef); + fail("Shouldn't be able to delete the web project since not a content manager"); + } + catch (AccessDeniedException exception) + { + // Expected + } + + // Switch back to admin + AuthenticationUtil.setCurrentUser(USER_ADMIN); + + // Note: All admin authorities are implicitly content managers (across all web projects) even if not explicitly invited + assertTrue(wpService.isContentManager(wpInfo.getStoreId(), USER_ADMIN)); + + assertEquals(0, wpService.listWebUsers(wpNodeRef).size()); + + // delete web project + wpService.deleteWebProject(wpNodeRef); + } + + public void testPseudoScaleTest() + { + long start = System.currentTimeMillis(); + + long split = start; + + for (int i = 1; i <= SCALE_USERS; i++) + { + createUser(TEST_USER+"-"+i); + } + + System.out.println("testPseudoScaleTest: created "+SCALE_USERS+" users in "+(System.currentTimeMillis()-split)+" msecs"); + + split = System.currentTimeMillis(); + + for (int i = 1; i <= SCALE_WEBPROJECTS; i++) + { + wpService.createWebProject(TEST_WEBPROJ_DNS+"-"+i, TEST_WEBPROJ_NAME+"-"+i, TEST_TITLE, TEST_DESCRIPTION); // ignore return + } + + System.out.println("testPseudoScaleTest: created "+SCALE_WEBPROJECTS+" web projects in "+(System.currentTimeMillis()-split)+" msecs"); + + split = System.currentTimeMillis(); + + for (int i = 1; i <= SCALE_WEBPROJECTS; i++) + { + WebProjectInfo wpInfo = wpService.getWebProject(TEST_WEBPROJ_DNS+"-"+i); + for (int j = 1; j <= SCALE_WEBAPPS; j++) + { + wpService.createWebApp(wpInfo.getNodeRef(), TEST_WEBAPP+"-"+j, TEST_WEBAPP+"-"+j); + } + } + + System.out.println("testPseudoScaleTest: created additional "+SCALE_WEBAPPS+" web apps in each of "+SCALE_WEBPROJECTS+" web projects in "+(System.currentTimeMillis()-split)+" msecs"); + + split = System.currentTimeMillis(); + + for (int i = 1; i <= SCALE_WEBPROJECTS; i++) + { + WebProjectInfo wpInfo = wpService.getWebProject(TEST_WEBPROJ_DNS+"-"+i); + Map userRoles = new HashMap(SCALE_USERS); + for (int j = 1; j <= SCALE_USERS; j++) + { + userRoles.put(TEST_USER+"-"+j, WCMUtil.ROLE_CONTENT_MANAGER); + } + wpService.inviteWebUsersGroups(wpInfo.getNodeRef(), userRoles); + } + + System.out.println("testPseudoScaleTest: invited "+SCALE_USERS+" content managers to each of "+SCALE_WEBPROJECTS+" web projects in "+(System.currentTimeMillis()-split)+" msecs"); + + split = System.currentTimeMillis(); + + for (int i = 1; i <= SCALE_USERS; i++) + { + wpService.listWebProjects(TEST_USER+"-"+i); // ignore return + } + + System.out.println("testPseudoScaleTest: list web projects for "+SCALE_USERS+" content managers in "+(System.currentTimeMillis()-split)+" msecs"); + + split = System.currentTimeMillis(); + + for (int i = 1; i <= SCALE_WEBPROJECTS; i++) + { + WebProjectInfo wpInfo = wpService.getWebProject(TEST_WEBPROJ_DNS+"-"+i); + wpService.deleteWebProject(wpInfo.getNodeRef()); + } + + System.out.println("testPseudoScaleTest: deleted "+SCALE_USERS+" web projects in "+(System.currentTimeMillis()-split)+" msecs"); + + split = System.currentTimeMillis(); + + for (int i = 1; i <= SCALE_USERS; i++) + { + deleteUser(TEST_USER+"-"+i); + } + + System.out.println("testPseudoScaleTest: deleted "+SCALE_USERS+" users in "+(System.currentTimeMillis()-split)+" msecs"); + } + + + /* + // == Test the JavaScript API == + + public void testJSAPI() throws Exception + { + ScriptLocation location = new ClasspathScriptLocation("org/alfresco/wcm/script/test_webProjectService.js"); + scriptService.executeScript(location, new HashMap(0)); + } + */ +} diff --git a/source/java/org/alfresco/wcm/webproject/script/WebProject.java b/source/java/org/alfresco/wcm/webproject/script/WebProject.java new file mode 100644 index 0000000000..a2ee2504e1 --- /dev/null +++ b/source/java/org/alfresco/wcm/webproject/script/WebProject.java @@ -0,0 +1,214 @@ +/* + * 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.wcm.webproject.script; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.jscript.ScriptableHashMap; +import org.alfresco.wcm.webproject.WebProjectInfo; +import org.alfresco.wcm.webproject.WebProjectService; + +import com.sun.corba.se.spi.orbutil.fsm.Guard.Result; + + +/** + * WebProject object to expose via JavaScript + * + */ +public class WebProject implements Serializable +{ + public static final String ROLE_CONTENT_MANAGER = "ContentManager"; + public static final String ROLE_CONTENT_PUBLISHER = "ContentPublisher"; + public static final String ROLE_CONTENT_REVIEWER = "ContentReviewer"; + public static final String ROLE_CONTENT_CONTRIBUTOR = "ContentContributor"; + + /** + * + */ + private static final long serialVersionUID = -2194205151549790079L; + + WebProjectService service; + + WebProjectInfo info; + + private String name; + private String title; + private String description; + private boolean isTemplate; + private String webProjectRef; + + /* + * Constructor for Outbound WebProjects + */ + public WebProject(WebProjectInfo info, WebProjectService service) + { + this.info = info; + this.name = info.getName(); + this.title = info.getTitle(); + this.description = info.getDescription(); + this.isTemplate = info.isTemplate(); + this.webProjectRef = info.getStoreId(); + this.service = service; + } + + public void setName(String name) { + this.name = name; + if(info != null) { + info.setName(name); + } + } + public String getName() { + return name; + } + + public void setTitle(String title) { + this.title = title; + if(info != null) { + info.setTitle(title); + } + } + public String getTitle() { + return title; + } + + public void setDescription(String description) { + this.description = description; + if(info != null) { + info.setDescription(description); + } + } + + public String getDescription() { + return description; + } + + + public void setTemplate(boolean isTemplate) { + this.isTemplate = isTemplate; + if(info != null) { + info.setIsTemplate(isTemplate); + } + } + + public boolean isTemplate() { + return isTemplate; + } + + // read-only property + public void setWebProjectRef(String webProjectRef) { + this.webProjectRef = webProjectRef; + } + + // + public String getWebProjectRef() { + return webProjectRef; + } + + /** + * delete this web project + */ + public void deleteWebProject() + { + service.deleteWebProject(webProjectRef); + } + + /** + * update this web project + */ + public void save() + { + service.updateWebProject(info); + } + + /** + * Gets a user's role on this site. + *

+ * If the user is not a member of the site then null is returned. + * + * @param userName user name + * @return String user's role or null if not a member + */ + public String getMembersRole(String userName) + { + return service.getWebUserRole(webProjectRef, userName); + } + + /** + * Sets the membership details for a user. + *

+ * If the user is not already a member of the web project then they are invited with the role + * given. + *

+ * Only a content manager can modify memberships and there must be at least one conttent manager at + * all times. + * + * @param userName user name + * @param role site role + */ + public void addMembership(String userName, String role) + { + service.inviteWebUser(webProjectRef, userName, role); + } + + /** + * Removes a users membership of the web project. + * + * Note: this will cascade delete the user's sandboxes without warning (even if there are modified items) + *

+ * + * @param userName user name + */ + public void removeMembership(String userName) + { + service.uninviteWebUser(webProjectRef, userName); + } + + /** + * Gets a map of members of the web project with their role within the web project. + *

+ * @return ScriptableHashMap list of members of site with their roles + */ + public ScriptableHashMap listMembers() + { + Map members = service.listWebUsers(webProjectRef); + + ScriptableHashMap result = new ScriptableHashMap(); + result.putAll(members); + + return result; + } + + /** + * List the role (name) for a WCM project + * @return the roles for a WCM project + */ + public ScriptableHashMap getRoles() + { + // TODO Not yet implemented. + ScriptableHashMap result = new ScriptableHashMap(); + return result; + } +} diff --git a/source/java/org/alfresco/wcm/webproject/script/WebProjects.java b/source/java/org/alfresco/wcm/webproject/script/WebProjects.java new file mode 100644 index 0000000000..e9242d34d0 --- /dev/null +++ b/source/java/org/alfresco/wcm/webproject/script/WebProjects.java @@ -0,0 +1,134 @@ +/* + * 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.wcm.webproject.script; + +import java.util.List; + +import org.alfresco.repo.jscript.BaseScopableProcessorExtension; +import org.alfresco.repo.model.Repository; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.wcm.webproject.WebProjectInfo; +import org.alfresco.wcm.webproject.WebProjectService; + + +/** + * Script object representing the wcm web projects script object. + * + * This class is the root for the script api to use wcm web projects. + */ +public class WebProjects extends BaseScopableProcessorExtension +{ + /** Service Registry */ + private ServiceRegistry serviceRegistry; + + /** The site service */ + private WebProjectService webProjectService; + + /** + * Sets the Service Registry + * + * @param serviceRegistry + */ + public void setServiceRegistry(ServiceRegistry serviceRegistry) + { + this.serviceRegistry = serviceRegistry; + } + + /** + * Set the wcm web project service + * + * @param webProjectService the wcm web project service + */ + public void setWebProjectService(WebProjectService webProjectService) + { + this.webProjectService = webProjectService; + } + + /** + * create web project + * @param name + * @param title + * @param description + * @return + */ + public WebProject createWebProject(String dnsName, String name, String title, String description ) + { + WebProjectInfo info = webProjectService.createWebProject(dnsName, name, title, description); + return new WebProject(info, webProjectService); + } + + /** + * Get an existing wcm web project + * @param webProjectRef + * @return the wcm web project + */ + public WebProject getWebProject(String webProjectRef) + { + WebProjectInfo info = webProjectService.getWebProject(webProjectRef); + + if(info != null){ + WebProject retVal = new WebProject(info, webProjectService); + return retVal; + } + return null; + } + + /* + * list All Web Projects + */ + public WebProject[] listWebProjects() + { + + List projects = webProjectService.listWebProjects(); + + WebProject[] ret = new WebProject[projects.size()]; + + int i= 0; + for(WebProjectInfo info : projects) + { + ret[i++] = new WebProject(info, webProjectService); + } + return ret; + } + + /* + * list All Web Projects which have the userName as a member + */ + public WebProject[] listWebProjects(String userName) + { + + List projects = webProjectService.listWebProjects(userName); + + WebProject[] ret = new WebProject[projects.size()]; + + int i= 0; + for(WebProjectInfo info : projects) + { + ret[i++] = new WebProject(info, webProjectService); + } + return ret; + } +}