diff --git a/config/alfresco/application-context.xml b/config/alfresco/application-context.xml index 6a9fdf53e8..1668af9ed5 100644 --- a/config/alfresco/application-context.xml +++ b/config/alfresco/application-context.xml @@ -41,6 +41,7 @@ + diff --git a/config/alfresco/model/siteModel.xml b/config/alfresco/model/siteModel.xml new file mode 100644 index 0000000000..f8861a534e --- /dev/null +++ b/config/alfresco/model/siteModel.xml @@ -0,0 +1,49 @@ + + + + + + + + Site Model + Roy Wetherall + 1.0 + + + + + + + + + + + + + + + + + + + + + + + + Site + cm:folder + + + Site Preset + d:text + + + + cm:titled + + + + + + \ No newline at end of file diff --git a/config/alfresco/model/sitePermissionDefinitions.xml b/config/alfresco/model/sitePermissionDefinitions.xml new file mode 100644 index 0000000000..839bc43bf3 --- /dev/null +++ b/config/alfresco/model/sitePermissionDefinitions.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/alfresco/site-services-context.xml b/config/alfresco/site-services-context.xml new file mode 100644 index 0000000000..9cabf4cf0c --- /dev/null +++ b/config/alfresco/site-services-context.xml @@ -0,0 +1,37 @@ + + + + + + + + + alfresco/model/siteModel.xml + + + + + + + + + + + + + + + + + + + + + + siteService + + + + + + diff --git a/source/java/org/alfresco/repo/content/transform/ContentTransformer.java b/source/java/org/alfresco/repo/content/transform/ContentTransformer.java index 5859aaaa46..495ec7c903 100644 --- a/source/java/org/alfresco/repo/content/transform/ContentTransformer.java +++ b/source/java/org/alfresco/repo/content/transform/ContentTransformer.java @@ -39,31 +39,6 @@ import org.alfresco.service.cmr.repository.TransformationOptions; */ public interface ContentTransformer extends ContentWorker { - /** - * Transform option constants - * - * It is up to the transformation implementation whether these - * options are used, but they should be considered optional and their absence - * should not interfere with the execution of the transformer. - */ - //public static final String OPT_SOURCE_NODEREF = "sourceNodeRef"; - //public static final String OPT_DESTINATION_NODEREF = "destinationNodeRef"; - - /** - * Provides the approximate accuracy with which this transformer can - * transform from one mimetype to another. - *

- * This method is used to determine, up front, which of a set of - * transformers will be used to perform a specific transformation. - * - * @param sourceMimetype the source mimetype - * @param targetMimetype the target mimetype - * @return Returns a score 0.0 to 1.0. 0.0 indicates that the - * transformation cannot be performed at all. 1.0 indicates that - * the transformation can be performed perfectly. - */ - //public double getReliability(String sourceMimetype, String targetMimetype); - /** * Indicates whether the provided source mimetype can be transformed into the target mimetype with * the options specified by this content transformer. @@ -76,11 +51,16 @@ public interface ContentTransformer extends ContentWorker public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options); /** + * Indicates whether given the provided transformation parmaters this transformer can prvide an explict + * transformation. * - * @param sourceMimetype - * @param targetMimetype - * @param options - * @return + * An explict transformation indicates that the transformation happens directly and not as a result of + * another transformation process. Explict transformation always take presidence over normal transformations. + * + * @param sourceMimetype the source mimetype + * @param targetMimetype the target mimetype + * @param options the transformation options + * @return boolean true if it is an explicit transformation, flase otherwise */ public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options); diff --git a/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java b/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java index 54f5a7f7d9..b1bffeb943 100644 --- a/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java +++ b/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java @@ -48,13 +48,6 @@ public class ContentTransformerRegistry private static final Log logger = LogFactory.getLog(ContentTransformerRegistry.class); private List transformers; - - /** Cache of previously used transactions */ - //private Map> transformationCache; - /** Controls read access to the transformation cache */ - //private Lock transformationCacheReadLock; - /** controls write access to the transformation cache */ - //private Lock transformationCacheWriteLock; /** * @param mimetypeMap all the mimetypes available to the system @@ -62,34 +55,8 @@ public class ContentTransformerRegistry public ContentTransformerRegistry() { this.transformers = new ArrayList(10); - - //transformationCache = new HashMap>(17); - - // create lock objects for access to the cache - //ReadWriteLock transformationCacheLock = new ReentrantReadWriteLock(); - //transformationCacheReadLock = transformationCacheLock.readLock(); - //transformationCacheWriteLock = transformationCacheLock.writeLock(); } - /** - * Register an individual transformer against a specific transformation. This transformation - * will take precedence over any of the generally-registered transformers. - * - * @param key the mapping from one mimetype to the next - * @param transformer the content transformer - */ - //public void addExplicitTransformer(TransformationKey key, ContentTransformer transformer) - //{ - // transformationCache.put(key, Collections.singletonList(transformer)); - // done - // if (logger.isDebugEnabled()) - // { - // logger.debug("Registered explicit transformation: \n" + - // " key: " + key + "\n" + - // " transformer: " + transformer); - // } - // } - /** * Registers an individual transformer that can be queried to check for applicability. * @@ -105,29 +72,6 @@ public class ContentTransformerRegistry " transformer: " + transformer); } } - - /** - * Resets the transformation cache. This allows a fresh analysis of the best - * conversions based on actual average performance of the transformers. - */ -// public void resetCache() -// { -// // get a write lock on the cache -// transformationCacheWriteLock.lock(); -// try -// { -// transformationCache.clear(); -// } -// finally -// { -// transformationCacheWriteLock.unlock(); -// } -// // done -// if (logger.isDebugEnabled()) -// { -// logger.debug("Content transformation cache reset"); -// } -// } /** * Gets the best transformer possible. This is a combination of the most reliable @@ -137,41 +81,9 @@ public class ContentTransformerRegistry */ public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options) { - //TransformationKey key = new TransformationKey(sourceMimetype, targetMimetype); - List transformers = null; - //transformationCacheReadLock.lock(); - //try - //{ - // if (transformationCache.containsKey(key)) - // { - // the translation has been requested before - // it might have been null - // transformers = transformationCache.get(key); - // } - //} - // finally - // { - // transformationCacheReadLock.unlock(); - // } - - // if (transformers == null) - // { - // the translation has not been requested before - // get a write lock on the cache - // no double check done as it is not an expensive task - // transformationCacheWriteLock.lock(); - // try - // { - // find the most suitable transformer - may be empty list - transformers = findTransformers(sourceMimetype, targetMimetype, options); - // store the result even if it is null - // transformationCache.put(key, transformers); - // } - // finally - // { - // transformationCacheWriteLock.unlock(); - // } - //} + // Get the list of transformers + List transformers = findTransformers(sourceMimetype, targetMimetype, options); + // select the most performant transformer long bestTime = -1L; ContentTransformer bestTransformer = null; @@ -257,30 +169,6 @@ public class ContentTransformerRegistry } } } - -// double reliability = transformer.getReliability(sourceMimetype, targetMimetype); -// if (reliability <= 0.0) -// { -// // it is unusable -// continue; -// } -// else if (reliability < maxReliability) -// { -// // it is not the best one to use -// continue; -// } -// else if (reliability == maxReliability) -// { -// // it is as reliable as a previous transformer -// } -// else -// { -// // it is better than any previous transformer - wipe them -// bestTransformers.clear(); -// maxReliability = reliability; -// } -// // add the transformer to the list -// bestTransformers.add(transformer); } // done return transformers; diff --git a/source/java/org/alfresco/repo/jscript/ScriptUtils.java b/source/java/org/alfresco/repo/jscript/ScriptUtils.java index c5b23c54a0..7df71a8ca8 100644 --- a/source/java/org/alfresco/repo/jscript/ScriptUtils.java +++ b/source/java/org/alfresco/repo/jscript/ScriptUtils.java @@ -76,4 +76,17 @@ public final class ScriptUtils extends BaseScopableProcessorExtension NodeRef nodeRef = new NodeRef(nodeRefString); return (ScriptNode)new ValueConverter().convertValueForScript(this.services, getScope(), null, nodeRef); } + + /** + * Gets a boolean value from a string + * + * @see Boolean#parseBoolean(String) + * + * @param booleanString boolean string + * @return boolean the boolean value + */ + public boolean toBoolean(String booleanString) + { + return Boolean.parseBoolean(booleanString); + } } diff --git a/source/java/org/alfresco/repo/site/SiteInfo.java b/source/java/org/alfresco/repo/site/SiteInfo.java new file mode 100644 index 0000000000..c5960ab3b7 --- /dev/null +++ b/source/java/org/alfresco/repo/site/SiteInfo.java @@ -0,0 +1,86 @@ +/* + * 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.site; + +/** + * @author Roy Wetherall + */ +public class SiteInfo +{ + private String sitePreset; + private String shortName; + private String title; + private String description; + private boolean isPublic; + + public SiteInfo(String sitePreset, String shortName, String title, String description, boolean isPublic) + { + this.sitePreset = sitePreset; + this.shortName = shortName; + this.title = title; + this.description = description; + this.isPublic = isPublic; + } + + public String getSitePreset() + { + return sitePreset; + } + + public String getShortName() + { + return shortName; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public void setIsPublic(boolean isPublic) + { + this.isPublic = isPublic; + } + + public boolean getIsPublic() + { + return this.isPublic; + } +} diff --git a/source/java/org/alfresco/repo/site/SiteModel.java b/source/java/org/alfresco/repo/site/SiteModel.java new file mode 100644 index 0000000000..6320ef2ed0 --- /dev/null +++ b/source/java/org/alfresco/repo/site/SiteModel.java @@ -0,0 +1,49 @@ +/* + * 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.site; + +import org.alfresco.service.namespace.QName; + +/** + * Site models constants + * + * @author Roy Wetherall + */ +public interface SiteModel +{ + /** Site Model */ + public static final String SITE_MODEL_URL = "http://www.alfresco.org/model/site/1.0"; + public static final String SITE_MODEL_PREFIX = "st"; + + /** Site */ + public static final QName TYPE_SITE = QName.createQName(SITE_MODEL_URL, "site"); + public static final QName PROP_SITE_PRESET = QName.createQName(SITE_MODEL_URL, "sitePreset"); + + /** Site Permission */ + public static final String SITE_MANAGER = "SiteManager"; + public static final String SITE_COLLABORATOR = "SiteCollaborator"; + public static final String SITE_CONSUMER = "SiteConsumer"; +} + diff --git a/source/java/org/alfresco/repo/site/SiteService.java b/source/java/org/alfresco/repo/site/SiteService.java new file mode 100644 index 0000000000..4c2e0a3b7f --- /dev/null +++ b/source/java/org/alfresco/repo/site/SiteService.java @@ -0,0 +1,36 @@ +package org.alfresco.repo.site; + +import java.util.List; + +/** + * Site service fundamental API. + *

+ * This service API is designed to support the public facing Site APIs + * + * @author Roy Wetherall + */ +public interface SiteService +{ + /** + * Create a new site. + * + * @param sitePreset site preset name + * @param shortName site short name, must be unique + * @param title site title + * @param description site description + * @param isPublic whether the site is public or not + * @return SiteInfo information about the created site + */ + // TODO ... audit information + SiteInfo createSite(String sitePreset, String shortName, String title, String description, boolean isPublic); + + /** + * List the available sites. This list can optionally be filtered by site name and/or site preset. + * + * @param nameFilter name filter + * @param sitePresetFilter site preset filter + * @return List list of site information + */ + // TODO audit information + List listSites(String nameFilter, String sitePresetFilter); +} diff --git a/source/java/org/alfresco/repo/site/SiteServiceImpl.java b/source/java/org/alfresco/repo/site/SiteServiceImpl.java new file mode 100644 index 0000000000..edb92a4362 --- /dev/null +++ b/source/java/org/alfresco/repo/site/SiteServiceImpl.java @@ -0,0 +1,300 @@ +/* + * 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.site; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.avm.AVMRepository; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +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.repository.StoreRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.AccessPermission; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; +import org.alfresco.util.AbstractLifecycleBean; +import org.alfresco.util.PropertyMap; +import org.springframework.context.ApplicationEvent; + +/** + * Bootstraps the site AVN and DM stores + * + * @author Roy Wetherall + */ +public class SiteServiceImpl extends AbstractLifecycleBean implements SiteService, SiteModel +{ + public static final String SITE_AVM_STORE = "SiteStore"; + public static final StoreRef SITE_DM_STORE = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SiteStore"); + + private NodeService nodeService; + private SearchService searchService; + private AuthenticationService authenticationService; + private PermissionService permissionService; + private AuthenticationComponent authenticationComponent; + private AVMRepository AVMRepository; + private RetryingTransactionHelper retryingTransactionHelper; + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + public void setAuthenticationService(AuthenticationService authenticationService) + { + this.authenticationService = authenticationService; + } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public void setAuthenticationComponent(AuthenticationComponent authenticationComponent) + { + this.authenticationComponent = authenticationComponent; + } + + public void setAVMRepository(AVMRepository repository) + { + AVMRepository = repository; + } + + public void setRetryingTransactionHelper(RetryingTransactionHelper retryingTransactionHelper) + { + this.retryingTransactionHelper = retryingTransactionHelper; + } + + public SiteInfo createSite(String sitePreset, String shortName, String title, String description, boolean isPublic) + { + // TODO: + // 1. Check that the site preset exists + // 2. Check that the short name of the site isn't a duplicate + // 3. AVM create: + // 3a. Find the site preset AVM folder + // 3b. Create a new site folder in the correct location (named by the short name) + // 3c. Copy the contents of the site preset folder into the new site folder + // 3d. Mangle files as needed during copy ?? + // 4. DM create: + // 4a. Find the site preset DM folder ?? + // 4b. Create a new site in the correct location (named by short name) + // 4c. Set meta-data + // 4d. Set up memberships (copying from site preset DM folder??) + // 4e. Set up another details (rules) on site from DM preset folder ?? + // 5. Return created site information + + + + // 4. DM create .. create the DM object that represents the site + + // Get the site parent node reference + NodeRef siteParent = getDMSiteParent(shortName); + + // Create the site node + PropertyMap properties = new PropertyMap(4); + properties.put(ContentModel.PROP_NAME, shortName); + properties.put(SiteModel.PROP_SITE_PRESET, sitePreset); + properties.put(ContentModel.PROP_TITLE, title); + properties.put(ContentModel.PROP_DESCRIPTION, description); + NodeRef siteNodeRef = this.nodeService.createNode( + siteParent, + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, shortName), + SiteModel.TYPE_SITE, + properties).getChildRef(); + + // Set the memberhips details + this.permissionService.setInheritParentPermissions(siteNodeRef, false); + if (isPublic == true) + { + this.permissionService.setPermission(siteNodeRef, PermissionService.ALL_AUTHORITIES, SITE_CONSUMER, true); + } + + // 5. Return created site information + SiteInfo siteInfo = new SiteInfo(sitePreset, shortName, title, description, isPublic); + return siteInfo; + } + + private NodeRef getDMSiteParent(String shortName) + { + // TODO + // For now just return the site root, later we may build folder structure based on the shortname to + // spread the sites about + return getDMSiteRoot(); + } + + private NodeRef getDMSiteRoot() + { + // Get the root 'sites' folder + ResultSet resultSet = this.searchService.query(SITE_DM_STORE, SearchService.LANGUAGE_LUCENE, "PATH:\"cm:sites\""); + if (resultSet.length() == 0) + { + // TODO + throw new RuntimeException("No root sites folder exists"); + } + else if (resultSet.length() != 1) + { + // TODO + throw new RuntimeException("More than one root sites folder exists"); + } + NodeRef sitesRoot = resultSet.getNodeRef(0); + + // TODO + // In time we will use some sort of algorithm to spread the creation of sites across an arbitary structure + + return sitesRoot; + } + + public List listSites(String nameFilter, String sitePresetFilter) + { + // TODO + // - take into consideration the filters set + // - take into consideration that the sites may not just be in a flat list under the site root + // - should we be taking the list from the AVM store, since we can have an AVM site pointing to + // the default DM data site + + // TODO + // For now just return the list of sites present under the site root + NodeRef siteRoot = getDMSiteRoot(); + List assocs = this.nodeService.getChildAssocs(siteRoot, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); + List result = new ArrayList(assocs.size()); + for (ChildAssociationRef assoc : assocs) + { + result.add(createSiteInfo(assoc.getChildRef())); + } + + return result; + } + + private SiteInfo createSiteInfo(NodeRef siteNodeRef) + { + // Get the properties + Map properties = this.nodeService.getProperties(siteNodeRef); + String shortName = (String)properties.get(ContentModel.PROP_NAME); + String sitePreset = (String)properties.get(PROP_SITE_PRESET); + String title = (String)properties.get(ContentModel.PROP_TITLE); + String description = (String)properties.get(ContentModel.PROP_DESCRIPTION); + + // Determine whether the space is public or not + boolean isPublic = false; + Set permissions = this.permissionService.getAllSetPermissions(siteNodeRef); + for (AccessPermission permission : permissions) + { + if (permission.getAuthority().equals(PermissionService.ALL_AUTHORITIES) == true && + permission.getPermission().equals(SITE_CONSUMER) == true) + { + isPublic = true; + break; + } + } + + // Create and return the site information + SiteInfo siteInfo = new SiteInfo(sitePreset, shortName, title, description, isPublic); + return siteInfo; + } + + /** + * @see org.alfresco.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent) + */ + @Override + protected void onBootstrap(ApplicationEvent event) + { + // Ensure execution occures in a transaction + this.retryingTransactionHelper.doInTransaction( + new RetryingTransactionHelper.RetryingTransactionCallback() + { + public Object execute() throws Throwable + { + String currentUserName = SiteServiceImpl.this.authenticationComponent.getCurrentUserName(); + SiteServiceImpl.this.authenticationComponent.setSystemUserAsCurrentUser(); + try + { + // Bootstrap the site stores + bootstrapSiteStore(SITE_DM_STORE); + } + finally + { + if (currentUserName != null) + { + SiteServiceImpl.this.authenticationComponent.setCurrentUser(currentUserName); + } + else + { + SiteServiceImpl.this.authenticationComponent.clearCurrentSecurityContext(); + } + } + + return null; + } + }); + } + + /** + * @see org.alfresco.util.AbstractLifecycleBean#onShutdown(org.springframework.context.ApplicationEvent) + */ + @Override + protected void onShutdown(ApplicationEvent event) + { + // Do nothing + } + + /** + * Bootstrap the DM site store + * + * @param storeRef the store reference + */ + private void bootstrapSiteStore(StoreRef storeRef) + { + // Check to see if the sotre exists + if (this.nodeService.exists(storeRef) == false) + { + // Create the store + this.nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier()); + NodeRef rootNode = this.nodeService.getRootNode(storeRef); + + // Create the root folder where sites will be stored + this.nodeService.createNode(rootNode, + ContentModel.ASSOC_CHILDREN, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "sites"), + ContentModel.TYPE_FOLDER); + } + } +} diff --git a/source/java/org/alfresco/repo/site/SiteServiceImplTest.java b/source/java/org/alfresco/repo/site/SiteServiceImplTest.java new file mode 100644 index 0000000000..c26642d52c --- /dev/null +++ b/source/java/org/alfresco/repo/site/SiteServiceImplTest.java @@ -0,0 +1,144 @@ +/* + * 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.site; + +import java.util.HashMap; +import java.util.List; + +import org.alfresco.repo.jscript.ClasspathScriptLocation; +import org.alfresco.service.cmr.repository.ScriptLocation; +import org.alfresco.service.cmr.repository.ScriptService; +import org.alfresco.util.BaseAlfrescoSpringTest; + +/** + * Thumbnail service implementation unit test + * + * @author Roy Wetherall + */ +public class SiteServiceImplTest extends BaseAlfrescoSpringTest +{ + private static final String TEST_SITE_PRESET = "testSitePreset"; + private static final String TEST_SITE_PRESET_2 = "testSitePreset2"; + private static final String TEST_TITLE = "This is my title"; + private static final String TEST_DESCRIPTION = "This is my description"; + + private SiteService siteService; + + private ScriptService scriptService; + + /** + * Called during the transaction setup + */ + protected void onSetUpInTransaction() throws Exception + { + super.onSetUpInTransaction(); + + // Get the required services + this.siteService = (SiteService)this.applicationContext.getBean("siteService"); + this.scriptService = (ScriptService)this.applicationContext.getBean("ScriptService"); + } + + public void testCreateSite() throws Exception + { + // Create a public site + SiteInfo siteInfo = this.siteService.createSite(TEST_SITE_PRESET, "mySiteTest", TEST_TITLE, TEST_DESCRIPTION, true); + + // Check the site + checkSiteInfo(siteInfo, TEST_SITE_PRESET, "mySiteTest", TEST_TITLE, TEST_DESCRIPTION, true); + } + + private void checkSiteInfo( SiteInfo siteInfo, String expectedSitePreset, String expectedShortName, String expectedTitle, + String expectedDescription, boolean expectedIsPublic) + { + assertNotNull(siteInfo); + assertEquals(expectedSitePreset, siteInfo.getSitePreset()); + assertEquals(expectedShortName, siteInfo.getShortName()); + assertEquals(expectedTitle, siteInfo.getTitle()); + assertEquals(expectedDescription, siteInfo.getDescription()); + assertEquals(expectedIsPublic, siteInfo.getIsPublic()); + } + + public void testListSites() throws Exception + { + // TODO + // - check filters + // - check private excluded when not owner (or admin) + + // Check for no sites + List sites = this.siteService.listSites(null, null); + assertNotNull(sites); + assertTrue(sites.isEmpty()); + + // Create some sites + this.siteService.createSite(TEST_SITE_PRESET, "mySiteOne", TEST_TITLE, TEST_DESCRIPTION, true); + this.siteService.createSite(TEST_SITE_PRESET, "mySiteTwo", TEST_TITLE, TEST_DESCRIPTION, false); + this.siteService.createSite(TEST_SITE_PRESET_2, "mySiteThree", TEST_TITLE, TEST_DESCRIPTION, true); + this.siteService.createSite(TEST_SITE_PRESET_2, "mySiteFour", TEST_TITLE, TEST_DESCRIPTION, false); + + // Get all the sites + sites = this.siteService.listSites(null, null); + assertNotNull(sites); + assertEquals(4, sites.size()); + // Do detailed check of the site info objects + for (SiteInfo site : sites) + { + String shortName = site.getShortName(); + if (shortName.equals("mySiteOne") == true) + { + checkSiteInfo(site, TEST_SITE_PRESET, "mySiteOne", TEST_TITLE, TEST_DESCRIPTION, true); + } + else if (shortName.equals("mySiteTwo") == true) + { + checkSiteInfo(site, TEST_SITE_PRESET, "mySiteTwo", TEST_TITLE, TEST_DESCRIPTION, false); + } + else if (shortName.equals("mySiteThree") == true) + { + checkSiteInfo(site, TEST_SITE_PRESET_2, "mySiteThree", TEST_TITLE, TEST_DESCRIPTION, true); + } + else if (shortName.equals("mySiteFour") == true) + { + checkSiteInfo(site, TEST_SITE_PRESET_2, "mySiteFour", TEST_TITLE, TEST_DESCRIPTION, false); + } + else + { + fail("The shortname " + shortName + " is not recognised"); + } + } + + } + + public void testJSAPI() throws Exception + { + ScriptLocation location = new ClasspathScriptLocation("org/alfresco/repo/site/script/test_siteService.js"); + String result = (String)this.scriptService.executeScript(location, new HashMap(0)); + + // Check the result and fail if message returned + if (result != null && result.length() != 0) + { + fail("The site service text JS script failed: " + result); + } + } + +} diff --git a/source/java/org/alfresco/repo/site/script/ScriptSiteService.java b/source/java/org/alfresco/repo/site/script/ScriptSiteService.java new file mode 100644 index 0000000000..41f590badd --- /dev/null +++ b/source/java/org/alfresco/repo/site/script/ScriptSiteService.java @@ -0,0 +1,93 @@ +/* + * 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.site.script; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.jscript.BaseScopableProcessorExtension; +import org.alfresco.repo.site.SiteInfo; +import org.alfresco.repo.site.SiteService; + + +/** + * Script object representing the site service. + * + * @author Roy Wetherall + */ +public class ScriptSiteService extends BaseScopableProcessorExtension +{ + /** The site service */ + private SiteService siteService; + + /** + * Set the site service + * + * @param siteService the site service + */ + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + /** + * Create a new site. + *

+ * The site short name will be used to uniquely identify the site so it must be unique. + * + * @param sitePreset site preset + * @param shortName site short name + * @param title site title + * @param descripion site description + * @param isPublic whether the site is public or not + * @return Site the created site + */ + public Site createSite(String sitePreset, String shortName, String title, String descripion, boolean isPublic) + { + SiteInfo siteInfo = this.siteService.createSite(sitePreset, shortName, title, descripion, isPublic); + return new Site(siteInfo); + } + + /** + * List the sites available in the repository. The returned list can optionally be filtered by name and site + * preset. + *

+ * If no filters are specified then all the available sites are returned. + * + * @param nameFilter name filter + * @param sitePresetFilter site preset filter + * @return List a list of the site filtered as appropriate + */ + public List listSites(String nameFilter, String sitePresetFilter) + { + List siteInfos = this.siteService.listSites(nameFilter, sitePresetFilter); + List sites = new ArrayList(siteInfos.size()); + for (SiteInfo siteInfo : siteInfos) + { + sites.add(new Site(siteInfo)); + } + return sites; + } +} diff --git a/source/java/org/alfresco/repo/site/script/Site.java b/source/java/org/alfresco/repo/site/script/Site.java new file mode 100644 index 0000000000..e36f546459 --- /dev/null +++ b/source/java/org/alfresco/repo/site/script/Site.java @@ -0,0 +1,75 @@ +/* + * 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.site.script; + +import java.io.Serializable; + +import org.alfresco.repo.site.SiteInfo; + +/** + * @author Roy Wetherall + */ +public class Site implements Serializable +{ + private static final long serialVersionUID = 8013569574120957923L; + + private SiteInfo siteInfo; + + public Site(SiteInfo siteInfo) + { + this.siteInfo = siteInfo; + } + + public String getSitePreset() + { + return this.siteInfo.getSitePreset(); + } + + public String getShortName() + { + return this.siteInfo.getShortName(); + } + + public String getTitle() + { + return this.siteInfo.getTitle(); + } + + // TODO set title + + public String getDescription() + { + return this.siteInfo.getDescription(); + } + + // TODO set description + + public boolean getIsPublic() + { + return this.siteInfo.getIsPublic(); + } + + // TODO set isPublic +} diff --git a/source/java/org/alfresco/repo/site/script/test_siteService.js b/source/java/org/alfresco/repo/site/script/test_siteService.js new file mode 100644 index 0000000000..6271f43104 --- /dev/null +++ b/source/java/org/alfresco/repo/site/script/test_siteService.js @@ -0,0 +1,29 @@ +var failure = ""; + +// Try and create a site +var site = siteService.createSite("sitePreset", "siteShortName", "siteTitle", "siteDescription", true); + +// Check that the site details are correct +if (site.sitePreset != "sitePreset") +{ + failure += "\nSite preset is not set on created site"; +} +if (site.shortName != "siteShortName") +{ + failure += "\nSite short name is not set on created site"; +} +if (site.title != "siteTitle") +{ + failure += "\nSite title is not set on created site"; +} +if (site.description != "siteDescription") +{ + failure += "\nSite description is not set on created site"; +} +if (site.isPublic != true) +{ + failure += "\nCreated site should be marked public"; +} + +// Return the failure message +failure; \ No newline at end of file diff --git a/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java b/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java index 5eb7838594..bf1a797f5e 100644 --- a/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java +++ b/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java @@ -363,6 +363,8 @@ public class ThumbnailServiceImpl implements ThumbnailService /** * Determine whether the thumbnail meta-data matches the given mimetype and options * + * If mimetype and transformation options are null then match is guarenteed + * * @param thumbnail thumbnail node reference * @param mimetype mimetype * @param options transformation options @@ -372,26 +374,21 @@ public class ThumbnailServiceImpl implements ThumbnailService { boolean result = true; - // Check the mimetype - String thumbnailMimetype = ((ContentData)this.nodeService.getProperty(thumbnail, ContentModel.PROP_CONTENT)).getMimetype(); - if (mimetype.equals(thumbnailMimetype) == true) + if (mimetype != null) { - // TODO continue to check options ... + // Check the mimetype + String thumbnailMimetype = ((ContentData)this.nodeService.getProperty(thumbnail, ContentModel.PROP_CONTENT)).getMimetype(); + if (mimetype.equals(thumbnailMimetype) == false) + { + result = false; + } } - else + + if (result != false && options != null) { - result = false; + // TODO .. check for matching options here ... } return result; } - - /** - * @see org.alfresco.service.cmr.thumbnail.ThumbnailService#getThumbnails(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.lang.String) - */ - public List getThumbnails(NodeRef node, QName contentProperty, String mimetype) - { - return getThumbnails(node, contentProperty, mimetype, null); - } - } diff --git a/source/java/org/alfresco/service/cmr/thumbnail/ThumbnailService.java b/source/java/org/alfresco/service/cmr/thumbnail/ThumbnailService.java index c3f18dc6ca..c02a939bf7 100644 --- a/source/java/org/alfresco/service/cmr/thumbnail/ThumbnailService.java +++ b/source/java/org/alfresco/service/cmr/thumbnail/ThumbnailService.java @@ -74,37 +74,35 @@ public interface ThumbnailService void updateThumbnail(NodeRef thumbnail); /** + * Get's the thumbnail for a given content property with a given name. * - * @param node - * @param contentProperty - * @param thumbnailName - * @return + * Returns null if no thumbnail with that name for that content property is found. + * + * @param node node reference + * @param contentProperty content property name + * @param thumbnailName thumbnail name + * @return NodeRef the thumbnail node reference, null if not found */ @Auditable(key = Auditable.Key.ARG_0, parameters = {"node", "contentProperty", "thumbnailName"}) NodeRef getThumbnailByName(NodeRef node, QName contentProperty, String thumbnailName); /** + * Get's a list of thumbnail nodes for a given content property that match the provided mimetype and + * transformation options. * - * @param node - * @param contentProperty - * @param mimetype - * @param options - * @return + * Both mimetype and transformation options are optional parameters. If only one or other is specified the + * only the other is considered during. If neither are provided all thumbnails for that content property + * are returned. + * + * If no matches are found then an empty list is returned. + * + * @param node node reference + * @param contentProperty content property name + * @param mimetype mimetype + * @param options transformation options + * @return List list of matching thumbnail node references, empty if no matches found */ @Auditable(key = Auditable.Key.ARG_0, parameters = {"node", "contentProperty", "mimetype", "options"}) List getThumbnails(NodeRef node, QName contentProperty, String mimetype, TransformationOptions options); - /** - * @see ThumbnailService#getThumbnails(NodeRef, QName, String, TransformationOptions) - * - * Transformation options defaulted to null. - * - * @param node - * @param contentProperty - * @param mimetype - * @return - */ - @Auditable(key = Auditable.Key.ARG_0, parameters = {"node", "contentProperty", "mimetype"}) - List getThumbnails(NodeRef node, QName contentProperty, String mimetype); - }