diff --git a/config/alfresco/action-services-context.xml b/config/alfresco/action-services-context.xml index f0bde50bad..5053cd534a 100644 --- a/config/alfresco/action-services-context.xml +++ b/config/alfresco/action-services-context.xml @@ -14,6 +14,9 @@ + + + @@ -203,6 +206,11 @@ + + + {http://www.alfresco.org/model/content/1.0}content + + + + + {http://www.alfresco.org/model/content/1.0}content + + @@ -243,6 +256,11 @@ + + + {http://www.alfresco.org/model/content/1.0}content + + @@ -291,6 +309,11 @@ + + + {http://www.alfresco.org/model/content/1.0}content + + diff --git a/config/alfresco/cache-context.xml b/config/alfresco/cache-context.xml index f40fda1024..a65d4ff7e1 100644 --- a/config/alfresco/cache-context.xml +++ b/config/alfresco/cache-context.xml @@ -25,47 +25,6 @@ - - - - - - - - - - - - - - nullPermissionCache - - - 10000 - - - false - - - - - - - - - - - - - - - - nullPermissionTransactionalCache - - - 5000 - - diff --git a/config/alfresco/ehcache-default.xml b/config/alfresco/ehcache-default.xml index 0c3902f42c..84015637eb 100644 --- a/config/alfresco/ehcache-default.xml +++ b/config/alfresco/ehcache-default.xml @@ -151,14 +151,14 @@ - + @@ -167,9 +167,15 @@ maxElementsInMemory="25000" eternal="true" overflowToDisk="false"/> + + diff --git a/config/alfresco/hibernate-context.xml b/config/alfresco/hibernate-context.xml index 9e4866e27f..3c6cd954d5 100644 --- a/config/alfresco/hibernate-context.xml +++ b/config/alfresco/hibernate-context.xml @@ -65,6 +65,7 @@ ${cache.strategy} ${cache.strategy} + ${cache.strategy} ${cache.strategy} @@ -94,9 +95,6 @@ - - - diff --git a/config/alfresco/messages/content-model.properties b/config/alfresco/messages/content-model.properties index 2332896da5..a701ef2050 100644 --- a/config/alfresco/messages/content-model.properties +++ b/config/alfresco/messages/content-model.properties @@ -100,8 +100,8 @@ cm_contentmodel.association.cm_formats.description=Transformed Items cm_contentmodel.aspect.cm_templatable.title=Templatable cm_contentmodel.aspect.cm_templatable.description=Templatable -cm_contentmodel.aspect.cm_template.title=Template -cm_contentmodel.aspect.cm_template.description=Template +cm_contentmodel.property.cm_template.title=Template +cm_contentmodel.property.cm_template.description=Template cm_contentmodel.aspect.cm_complianceable.title=Complianceable cm_contentmodel.aspect.cm_complianceable.description=Complianceable diff --git a/config/alfresco/messages/system-model.properties b/config/alfresco/messages/system-model.properties index 3f8c4e0bf0..44563c435f 100644 --- a/config/alfresco/messages/system-model.properties +++ b/config/alfresco/messages/system-model.properties @@ -29,3 +29,12 @@ sys_systemmodel.property.sys_store-identifier.title=Store Identifier sys_systemmodel.property.sys_store-identifier.description=Store Identifier sys_systemmodel.property.sys_node-uuid.title=Node Identifier sys_systemmodel.property.sys_node-uuid.description=Node Identifier + +sys_systemmodel.aspect.sys_archived.title=Archived +sys_systemmodel.aspect.sys_archived.description=Archived Node +sys_systemmodel.property.sys_archivedBy.title=Archived By +sys_systemmodel.property.sys_archivedBy.description=Archived By +sys_systemmodel.property.sys_archivedDate.title=Archived Date +sys_systemmodel.property.sys_archivedDate.description=Archived Date +sys_systemmodel.property.sys_archivedOriginalPath.title=Original Location +sys_systemmodel.property.sys_archivedOriginalPath.description=Original Location diff --git a/source/java/org/alfresco/jcr/example/MixedExample.java b/source/java/org/alfresco/jcr/example/MixedExample.java deleted file mode 100644 index 9c7f1f41f2..0000000000 --- a/source/java/org/alfresco/jcr/example/MixedExample.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2005 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. - */ -package org.alfresco.jcr.example; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.alfresco.jcr.api.JCRNodeRef; -import org.alfresco.model.ContentModel; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - - - -/** - * Example that demonstrate use of JCR and Alfresco API calls. - * - * @author David Caruana - */ -public class MixedExample -{ - - public static void main(String[] args) - throws Exception - { - // Setup Spring and Transaction Service - ApplicationContext context = new ClassPathXmlApplicationContext("classpath:alfresco/application-context.xml"); - ServiceRegistry registry = (ServiceRegistry)context.getBean(ServiceRegistry.SERVICE_REGISTRY); - NodeService nodeService = (NodeService)registry.getNodeService(); - - // Retrieve Repository - Repository repository = (Repository)context.getBean("JCR.Repository"); - - // Login to workspace - // Note: Default workspace is the one used by Alfresco Web Client which contains all the Spaces - // and their documents - Session session = repository.login(new SimpleCredentials("admin", "admin".toCharArray())); - - try - { - // Retrieve Company Home - Node root = session.getRootNode(); - Node companyHome = root.getNode("app:company_home"); - - // Read Company Home Name - Property name = companyHome.getProperty("cm:name"); - System.out.println("Name = " + name.getString()); - - // Update Node via Alfresco Node Service API - NodeRef companyHomeRef = JCRNodeRef.getNodeRef(companyHome); - nodeService.setProperty(companyHomeRef, ContentModel.PROP_NAME, "Updated Company Home Name"); - - // Re-read via JCR - System.out.println("Updated name = " + name.getString()); - } - finally - { - session.logout(); - System.exit(0); - } - } - -} diff --git a/source/java/org/alfresco/jcr/example/SimpleExample.java b/source/java/org/alfresco/jcr/example/SimpleExample.java deleted file mode 100644 index fdb9f28751..0000000000 --- a/source/java/org/alfresco/jcr/example/SimpleExample.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2005 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. - */ -package org.alfresco.jcr.example; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.Repository; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - - - -/** - * Simple Example that demonstrate login and retrieval of top-level Spaces - * under Company Home. - * - * @author David Caruana - */ -public class SimpleExample -{ - - public static void main(String[] args) - throws Exception - { - // Setup Spring and Transaction Service - ApplicationContext context = new ClassPathXmlApplicationContext("classpath:alfresco/application-context.xml"); - - // Retrieve Repository - Repository repository = (Repository)context.getBean("JCR.Repository"); - - // Login to workspace - // Note: Default workspace is the one used by Alfresco Web Client which contains all the Spaces - // and their documents - Session session = repository.login(new SimpleCredentials("admin", "admin".toCharArray())); - - try - { - // Retrieve Company Home - Node root = session.getRootNode(); - Node companyHome = root.getNode("app:company_home"); - - // Iterator through children of Company Home - NodeIterator iterator = companyHome.getNodes(); - while(iterator.hasNext()) - { - Node child = iterator.nextNode(); - System.out.println(child.getName()); - - PropertyIterator propIterator = child.getProperties(); - while(propIterator.hasNext()) - { - Property prop = propIterator.nextProperty(); - if (!prop.getDefinition().isMultiple()) - { - System.out.println(" " + prop.getName() + " = " + prop.getString()); - } - } - } - } - finally - { - session.logout(); - System.exit(0); - } - - } - -} diff --git a/source/java/org/alfresco/jcr/example/WIKIExample.java b/source/java/org/alfresco/jcr/example/WIKIExample.java deleted file mode 100644 index 76ae7a8908..0000000000 --- a/source/java/org/alfresco/jcr/example/WIKIExample.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (C) 2005 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. - */ -package org.alfresco.jcr.example; - -import java.io.File; -import java.io.FileOutputStream; -import java.util.Calendar; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.PathNotFoundException; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; -import javax.jcr.Value; -import javax.jcr.Workspace; -import javax.jcr.query.Query; -import javax.jcr.query.QueryManager; -import javax.jcr.query.QueryResult; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; -import javax.jcr.version.VersionIterator; - -import org.alfresco.jcr.api.JCRNodeRef; -import org.alfresco.model.ContentModel; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.PermissionService; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.core.io.ClassPathResource; - - -/** - * Example that demonstrates read and write of a simple WIKI model - * - * Please refer to http://www.alfresco.org/mediawiki/index.php/Introducing_the_Alfresco_Java_Content_Repository_API - * for a complete description of this example. - * - * @author David Caruana - */ -public class WIKIExample -{ - - public static void main(String[] args) - throws Exception - { - // - // Repository Initialisation - // - - // access the Alfresco JCR Repository (here it's via programmatic approach, but it could also be injected) - System.out.println("Initialising Repository..."); - ApplicationContext context = new ClassPathXmlApplicationContext("classpath:org/alfresco/jcr/example/wiki-context.xml"); - Repository repository = (Repository)context.getBean("JCR.Repository"); - - // display information about the repository - System.out.println("Repository Description..."); - String[] keys = repository.getDescriptorKeys(); - for (String key : keys) - { - String value = repository.getDescriptor(key); - System.out.println(" " + key + " = " + value); - } - - // - // Create a WIKI structure - // - // Note: Here we're using the Alfresco Content Model and custom WIKI model to create - // WIKI pages and Content that are accessible via the Alfresco Web Client - // - - // login to workspace (here we rely on the default workspace defined by JCR.Repository bean) - Session session = repository.login(new SimpleCredentials("admin", "admin".toCharArray())); - - try - { - System.out.println("Creating WIKI..."); - - // first, access the company home - Node rootNode = session.getRootNode(); - System.out.println("Root node: path=" + rootNode.getPath() + ", type=" + rootNode.getPrimaryNodeType().getName()); - Node companyHome = rootNode.getNode("app:company_home"); - System.out.println("Company home node: path=" + companyHome.getPath() + ", type=" + companyHome.getPrimaryNodeType().getName()); - - // remove the WIKI structure if it already exists - try - { - Node encyclopedia = companyHome.getNode("wiki:encyclopedia"); - encyclopedia.remove(); - System.out.println("Existing WIKI found and removed"); - } - catch(PathNotFoundException e) - { - // doesn't exist, no need to remove - } - - // create the root WIKI folder - Node encyclopedia = companyHome.addNode("wiki:encyclopedia", "cm:folder"); - encyclopedia.setProperty("cm:name", "WIKI Encyclopedia"); - encyclopedia.setProperty("cm:description", ""); - - // create first wiki page - Node page1 = encyclopedia.addNode("wiki:entry1", "wiki:page"); - page1.setProperty("cm:name", "Rose"); - page1.setProperty("cm:description", ""); - page1.setProperty("cm:title", "The rose"); - page1.setProperty("cm:content", "A rose is a flowering shrub."); - page1.setProperty("wiki:category", new String[] {"flower", "plant", "rose"}); - - // create second wiki page - Node page2 = encyclopedia.addNode("wiki:entry2", "wiki:page"); - page2.setProperty("cm:name", "Shakespeare"); - page2.setProperty("cm:description", ""); - page2.setProperty("cm:title", "William Shakespeare"); - page2.setProperty("cm:content", "A famous poet who likes roses."); - page2.setProperty("wiki:restrict", true); - page2.setProperty("wiki:category", new String[] {"poet"}); - - // create an image (note: we're using an input stream to allow setting of binary content) - Node contentNode = encyclopedia.addNode("wiki:image", "cm:content"); - contentNode.setProperty("cm:name", "Dog"); - contentNode.setProperty("cm:description", ""); - contentNode.setProperty("cm:title", "My dog at New Year party"); - ClassPathResource resource = new ClassPathResource("org/alfresco/jcr/example/wikiImage.gif"); - contentNode.setProperty("cm:content", resource.getInputStream()); - - session.save(); - System.out.println("WIKI created"); - } - finally - { - session.logout(); - } - - // - // Access the WIKI structure - // - - // login to workspace (here we rely on the default workspace defined by JCR.Repository bean) - session = repository.login(new SimpleCredentials("admin", "admin".toCharArray())); - - try - { - System.out.println("Accessing WIKI..."); - - // access a wiki node directly from root node (by path and by UUID) - Node rootNode = session.getRootNode(); - Node encyclopedia = rootNode.getNode("app:company_home/wiki:encyclopedia"); - Node direct = session.getNodeByUUID(encyclopedia.getUUID()); - System.out.println("Found WIKI root correctly: " + encyclopedia.equals(direct)); - - // access a wiki property directly from root node - Node entry1 = rootNode.getNode("app:company_home/wiki:encyclopedia/wiki:entry1"); - String title = entry1.getProperty("cm:title").getString(); - System.out.println("Found WIKI page 1 title: " + title); - Calendar modified = entry1.getProperty("cm:modified").getDate(); - System.out.println("Found WIKI page 1 last modified date: " + modified.getTime()); - - // browse all wiki entries - System.out.println("WIKI browser:"); - NodeIterator entries = encyclopedia.getNodes(); - while (entries.hasNext()) - { - Node entry = entries.nextNode(); - outputContentNode(entry); - } - - // perform a search - System.out.println("Search results:"); - Workspace workspace = session.getWorkspace(); - QueryManager queryManager = workspace.getQueryManager(); - Query query = queryManager.createQuery("//app:company_home/wiki:encyclopedia/*[@cm:title = 'The rose']", Query.XPATH); - //Query query = queryManager.createQuery("//app:company_home/wiki:encyclopedia/*[jcr:contains(., 'rose')]", Query.XPATH); - QueryResult result = query.execute(); - NodeIterator it = result.getNodes(); - while (it.hasNext()) - { - Node n = it.nextNode(); - outputContentNode(n); - } - - // export content (system view format) - File systemView = new File("systemview.xml"); - FileOutputStream systemViewOut = new FileOutputStream(systemView); - session.exportSystemView("/app:company_home/wiki:encyclopedia", systemViewOut, false, false); - - // export content (document view format) - File docView = new File("docview.xml"); - FileOutputStream docViewOut = new FileOutputStream(docView); - session.exportDocumentView("/app:company_home/wiki:encyclopedia", docViewOut, false, false); - - System.out.println("WIKI exported"); - - } - finally - { - session.logout(); - } - - - // - // Advanced Usage - // - - // 1) Check-out / Check-in and version history retrieval - session = repository.login(new SimpleCredentials("admin", "admin".toCharArray())); - - try - { - // - // Version WIKI Page 1 - // - - // first, access the page - Node rootNode = session.getRootNode(); - Node entry1 = rootNode.getNode("app:company_home/wiki:encyclopedia/wiki:entry1"); - - // enable versioning capability - entry1.addMixin("mix:versionable"); - - // update the properties and content - entry1.setProperty("cm:title", "The Rise"); - entry1.setProperty("cm:content", "A rose is a flowering shrub of the genus Rosa."); - Value[] categories = entry1.getProperty("wiki:category").getValues(); - Value[] newCategories = new Value[categories.length + 1]; - System.arraycopy(categories, 0, newCategories, 0, categories.length); - newCategories[categories.length] = session.getValueFactory().createValue("poet"); - entry1.setProperty("wiki:category", newCategories); - - // and checkin the changes - entry1.checkin(); - - // checkout, fix wiki title and checkin again - entry1.checkout(); - entry1.setProperty("cm:title", "The Rose"); - entry1.checkin(); - - session.save(); - System.out.println("Versioned WIKI Page 1"); - } - finally - { - session.logout(); - } - - // 2) Permission checks - session = repository.login(new SimpleCredentials("admin", "admin".toCharArray())); - - try - { - // - // Browse WIKI Page 1 Version History - // - - // first, access the page - Node rootNode = session.getRootNode(); - Node entry1 = rootNode.getNode("app:company_home/wiki:encyclopedia/wiki:entry1"); - - // retrieve the history for thte page - VersionHistory versionHistory = entry1.getVersionHistory(); - VersionIterator versionIterator = versionHistory.getAllVersions(); - - // for each version, output the node as it was versioned - while (versionIterator.hasNext()) - { - Version version = versionIterator.nextVersion(); - NodeIterator nodeIterator = version.getNodes(); - - while (nodeIterator.hasNext()) - { - Node versionedNode = nodeIterator.nextNode(); - System.out.println(" Version: " + version.getName()); - System.out.println(" Created: " + version.getCreated().getTime()); - outputContentNode(versionedNode); - } - } - - - // - // Permission Checks - // - - System.out.println("Testing Permissions:"); - - // check for JCR 'read' permission - session.checkPermission("app:company_home/wiki:encyclopedia/wiki:entry1", "read"); - System.out.println("Session has 'read' permission on app:company_home/wiki:encyclopedia/wiki:entry1"); - - // check for Alfresco 'Take Ownership' permission - session.checkPermission("app:company_home/wiki:encyclopedia/wiki:entry1", PermissionService.TAKE_OWNERSHIP); - System.out.println("Session has 'take ownership' permission on app:company_home/wiki:encyclopedia/wiki:entry1"); - } - finally - { - session.logout(); - } - - - // - // Mixing JCR and Alfresco API calls - // - // Provide mimetype for WIKI content properties - // - - session = repository.login(new SimpleCredentials("admin", "admin".toCharArray())); - - try - { - // Retrieve the Alfresco Repository Service Registry - ServiceRegistry registry = (ServiceRegistry)context.getBean(ServiceRegistry.SERVICE_REGISTRY); - - // set the mime type on both WIKI pages and Image - Node rootNode = session.getRootNode(); - - // note: we have to checkout entry1 first - it's versioned - Node entry1 = rootNode.getNode("app:company_home/wiki:encyclopedia/wiki:entry1"); - entry1.checkout(); - setMimetype(registry, entry1, "cm:content", MimetypeMap.MIMETYPE_TEXT_PLAIN); - entry1.checkin(); - - Node entry2 = rootNode.getNode("app:company_home/wiki:encyclopedia/wiki:entry2"); - setMimetype(registry, entry2, "cm:content", MimetypeMap.MIMETYPE_TEXT_PLAIN); - Node image = rootNode.getNode("app:company_home/wiki:encyclopedia/wiki:image"); - setMimetype(registry, image, "cm:content", MimetypeMap.MIMETYPE_IMAGE_GIF); - - // save the changes - session.save(); - System.out.println("Updated WIKI mimetypes via Alfresco calls"); - } - finally - { - session.logout(); - } - - // exit - System.out.println("Completed successfully."); - System.exit(0); - } - - - private static void outputContentNode(Node node) - throws RepositoryException - { - // output common content properties - System.out.println(" Node " + node.getUUID()); - System.out.println(" title: " + node.getProperty("cm:title").getString()); - - // output properties specific to WIKI page - if (node.getPrimaryNodeType().getName().equals("wiki:page")) - { - System.out.println(" content: " + node.getProperty("cm:content").getString()); - System.out.println(" restrict: " + node.getProperty("wiki:restrict").getString()); - - // output multi-value property - Property categoryProperty = node.getProperty("wiki:category"); - Value[] categories = categoryProperty.getValues(); - for (Value category : categories) - { - System.out.println(" category: " + category.getString()); - } - } - } - - - private static void setMimetype(ServiceRegistry registry, Node node, String propertyName, String mimeType) - throws RepositoryException - { - // convert the JCR Node to an Alfresco Node Reference - NodeRef nodeRef = JCRNodeRef.getNodeRef(node); - - // retrieve the Content Property (represented as a ContentData object in Alfresco) - NodeService nodeService = registry.getNodeService(); - ContentData content = (ContentData)nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT); - - // update the Mimetype - content = ContentData.setMimetype(content, mimeType); - nodeService.setProperty(nodeRef, ContentModel.PROP_CONTENT, content); - } - -} diff --git a/source/java/org/alfresco/jcr/example/wiki-context.xml b/source/java/org/alfresco/jcr/example/wiki-context.xml deleted file mode 100644 index 005230ed3f..0000000000 --- a/source/java/org/alfresco/jcr/example/wiki-context.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - org/alfresco/jcr/example/wikiModel.xml - - - - - diff --git a/source/java/org/alfresco/jcr/example/wikiImage.gif b/source/java/org/alfresco/jcr/example/wikiImage.gif deleted file mode 100644 index a3e1ca59bd..0000000000 Binary files a/source/java/org/alfresco/jcr/example/wikiImage.gif and /dev/null differ diff --git a/source/java/org/alfresco/jcr/example/wikiModel.xml b/source/java/org/alfresco/jcr/example/wikiModel.xml deleted file mode 100644 index 1b0642a7b5..0000000000 --- a/source/java/org/alfresco/jcr/example/wikiModel.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - WIKI Page - cm:content - - - d:boolean - false - - - d:text - true - - - - cm:titled - - - - - - diff --git a/source/java/org/alfresco/jcr/item/NodeImpl.java b/source/java/org/alfresco/jcr/item/NodeImpl.java index a6ef2f0c7e..ee4483ef8f 100644 --- a/source/java/org/alfresco/jcr/item/NodeImpl.java +++ b/source/java/org/alfresco/jcr/item/NodeImpl.java @@ -62,7 +62,6 @@ import org.alfresco.jcr.util.JCRProxyFactory; import org.alfresco.jcr.version.VersionHistoryImpl; import org.alfresco.jcr.version.VersionImpl; import org.alfresco.model.ContentModel; -import org.alfresco.repo.version.VersionModel; import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition; import org.alfresco.service.cmr.dictionary.ClassDefinition; @@ -74,7 +73,6 @@ 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.Path; -import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.Path.Element; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.version.VersionService; @@ -230,7 +228,8 @@ public class NodeImpl extends ItemImpl implements Node Map childAssocs = classDef.getChildAssociations(); for (ChildAssociationDefinition childAssocDef : childAssocs.values()) { - if (dictionaryService.isSubClass(nodeType, childAssocDef.getTargetClass().getName())) + QName targetClass = childAssocDef.getTargetClass().getName(); + if (dictionaryService.isSubClass(nodeType, targetClass)) { if (nodeTypeChildAssocDef != null) { diff --git a/source/java/org/alfresco/repo/action/ActionDefinitionImpl.java b/source/java/org/alfresco/repo/action/ActionDefinitionImpl.java index 2eaa034498..91fc5a6ea8 100644 --- a/source/java/org/alfresco/repo/action/ActionDefinitionImpl.java +++ b/source/java/org/alfresco/repo/action/ActionDefinitionImpl.java @@ -16,7 +16,10 @@ */ package org.alfresco.repo.action; +import java.util.List; + import org.alfresco.service.cmr.action.ActionDefinition; +import org.alfresco.service.namespace.QName; /** * Rule action implementation class @@ -35,6 +38,9 @@ public class ActionDefinitionImpl extends ParameterizedItemDefinitionImpl * The rule action executor */ private String ruleActionExecutor; + + /** List of applicable types */ + private List applicableTypes; /** * Constructor @@ -65,4 +71,24 @@ public class ActionDefinitionImpl extends ParameterizedItemDefinitionImpl { return ruleActionExecutor; } + + /** + * Gets the list of applicable types + * + * @return the list of qnames + */ + public List getApplicableTypes() + { + return this.applicableTypes; + } + + /** + * Sets the list of applicable types + * + * @param applicableTypes the applicable types + */ + public void setApplicableTypes(List applicableTypes) + { + this.applicableTypes = applicableTypes; + } } diff --git a/source/java/org/alfresco/repo/action/ActionServiceImpl.java b/source/java/org/alfresco/repo/action/ActionServiceImpl.java index a16a2ceccb..f7dad34e08 100644 --- a/source/java/org/alfresco/repo/action/ActionServiceImpl.java +++ b/source/java/org/alfresco/repo/action/ActionServiceImpl.java @@ -38,6 +38,7 @@ import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.action.ActionServiceException; import org.alfresco.service.cmr.action.CompositeAction; import org.alfresco.service.cmr.action.ParameterizedItem; +import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; @@ -98,6 +99,9 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A */ private SearchService searchService; + /** The dictionary service */ + private DictionaryService dictionaryService; + /** The authentication component */ private AuthenticationComponent authenticationComponent; @@ -161,6 +165,16 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A this.authenticationComponent = authenticationComponent; } + /** + * Set the dictionary service + * + * @param dictionaryService the dictionary service + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + /** * Set the asynchronous action execution queue * @@ -217,6 +231,44 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A { return new ArrayList(this.actionDefinitions.values()); } + + /** + * @see org.alfresco.service.cmr.action.ActionService#getActionDefinitions(org.alfresco.service.cmr.repository.NodeRef) + */ + public List getActionDefinitions(NodeRef nodeRef) + { + if (nodeRef == null) + { + return getActionDefinitions(); + } + else + { + // TODO for now we will only filter by type, we will introduce filtering by aspect later + QName nodeType = this.nodeService.getType(nodeRef); + List result = new ArrayList(); + for (ActionDefinition actionDefinition : getActionDefinitions()) + { + List appliciableTypes = actionDefinition.getApplicableTypes(); + if (appliciableTypes != null && appliciableTypes.isEmpty() == false) + { + for (QName applicableType : actionDefinition.getApplicableTypes()) + { + if (this.dictionaryService.isSubClass(nodeType, applicableType)) + { + result.add(actionDefinition); + break; + } + } + } + else + { + result.add(actionDefinition); + } + } + + return result; + } + } /** * @see org.alfresco.service.cmr.action.ActionService#getActionConditionDefinition(java.lang.String) diff --git a/source/java/org/alfresco/repo/action/ActionServiceImplTest.java b/source/java/org/alfresco/repo/action/ActionServiceImplTest.java index d339852e14..6af845cda7 100644 --- a/source/java/org/alfresco/repo/action/ActionServiceImplTest.java +++ b/source/java/org/alfresco/repo/action/ActionServiceImplTest.java @@ -55,6 +55,7 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest private static final String BAD_NAME = "badName"; private NodeRef nodeRef; + private NodeRef folder; @Override protected void onSetUpInTransaction() throws Exception @@ -71,6 +72,12 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest this.nodeRef, ContentModel.PROP_CONTENT, new ContentData(null, MimetypeMap.MIMETYPE_TEXT_PLAIN, 0L, null)); + this.folder = this.nodeService.createNode( + this.rootNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName("{test}testFolder"), + ContentModel.TYPE_FOLDER).getChildRef(); + } /** @@ -94,11 +101,17 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest List defintions = this.actionService.getActionDefinitions(); assertNotNull(defintions); assertFalse(defintions.isEmpty()); + int totalCount = defintions.size(); for (ActionDefinition definition : defintions) { System.out.println(definition.getTitle()); } + + // Get the action defintions for a folder type (there should be less than the total available) + List definitions = this.actionService.getActionDefinitions(this.folder); + assertNotNull(definitions); + assertTrue(totalCount > definitions.size()); } /** diff --git a/source/java/org/alfresco/repo/action/ParameterizedItemAbstractBase.java b/source/java/org/alfresco/repo/action/ParameterizedItemAbstractBase.java index a1bd4f882f..28843c9cf1 100644 --- a/source/java/org/alfresco/repo/action/ParameterizedItemAbstractBase.java +++ b/source/java/org/alfresco/repo/action/ParameterizedItemAbstractBase.java @@ -73,7 +73,7 @@ public abstract class ParameterizedItemAbstractBase extends CommonResourceAbstra protected List getParameterDefintions() { List result = new ArrayList(); - addParameterDefintions(result); + addParameterDefinitions(result); return result; } @@ -82,7 +82,7 @@ public abstract class ParameterizedItemAbstractBase extends CommonResourceAbstra * * @param paramList the parameter definitions list */ - protected abstract void addParameterDefintions(List paramList); + protected abstract void addParameterDefinitions(List paramList); /** * Sets the action service diff --git a/source/java/org/alfresco/repo/action/evaluator/CompareMimeTypeEvaluator.java b/source/java/org/alfresco/repo/action/evaluator/CompareMimeTypeEvaluator.java index 9afded0705..7618ee5b3f 100644 --- a/source/java/org/alfresco/repo/action/evaluator/CompareMimeTypeEvaluator.java +++ b/source/java/org/alfresco/repo/action/evaluator/CompareMimeTypeEvaluator.java @@ -83,11 +83,11 @@ public class CompareMimeTypeEvaluator extends ComparePropertyValueEvaluator } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { - super.addParameterDefintions(paramList); + super.addParameterDefinitions(paramList); } } diff --git a/source/java/org/alfresco/repo/action/evaluator/ComparePropertyValueEvaluator.java b/source/java/org/alfresco/repo/action/evaluator/ComparePropertyValueEvaluator.java index f44f2cf82c..0074840c25 100644 --- a/source/java/org/alfresco/repo/action/evaluator/ComparePropertyValueEvaluator.java +++ b/source/java/org/alfresco/repo/action/evaluator/ComparePropertyValueEvaluator.java @@ -145,7 +145,7 @@ public class ComparePropertyValueEvaluator extends ActionConditionEvaluatorAbstr * Add paremeter defintions */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_PROPERTY, DataTypeDefinition.QNAME, false, getParamDisplayLabel(PARAM_PROPERTY))); paramList.add(new ParameterDefinitionImpl(PARAM_CONTENT_PROPERTY, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_CONTENT_PROPERTY))); diff --git a/source/java/org/alfresco/repo/action/evaluator/HasAspectEvaluator.java b/source/java/org/alfresco/repo/action/evaluator/HasAspectEvaluator.java index a5e5da26b3..1fbd4c0b6b 100644 --- a/source/java/org/alfresco/repo/action/evaluator/HasAspectEvaluator.java +++ b/source/java/org/alfresco/repo/action/evaluator/HasAspectEvaluator.java @@ -73,10 +73,10 @@ public class HasAspectEvaluator extends ActionConditionEvaluatorAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_ASPECT, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_ASPECT))); } diff --git a/source/java/org/alfresco/repo/action/evaluator/HasVersionHistoryEvaluator.java b/source/java/org/alfresco/repo/action/evaluator/HasVersionHistoryEvaluator.java index dccdf4a0f4..fc09d35034 100644 --- a/source/java/org/alfresco/repo/action/evaluator/HasVersionHistoryEvaluator.java +++ b/source/java/org/alfresco/repo/action/evaluator/HasVersionHistoryEvaluator.java @@ -81,10 +81,10 @@ public class HasVersionHistoryEvaluator extends ActionConditionEvaluatorAbstract } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { } diff --git a/source/java/org/alfresco/repo/action/evaluator/InCategoryEvaluator.java b/source/java/org/alfresco/repo/action/evaluator/InCategoryEvaluator.java index 3d0761b948..3150ce6603 100644 --- a/source/java/org/alfresco/repo/action/evaluator/InCategoryEvaluator.java +++ b/source/java/org/alfresco/repo/action/evaluator/InCategoryEvaluator.java @@ -81,7 +81,7 @@ public class InCategoryEvaluator extends ActionConditionEvaluatorAbstractBase * Add the parameter definitions */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_CATEGORY_ASPECT, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_CATEGORY_ASPECT))); paramList.add(new ParameterDefinitionImpl(PARAM_CATEGORY_VALUE, DataTypeDefinition.NODE_REF, true, getParamDisplayLabel(PARAM_CATEGORY_VALUE))); diff --git a/source/java/org/alfresco/repo/action/evaluator/IsSubTypeEvaluator.java b/source/java/org/alfresco/repo/action/evaluator/IsSubTypeEvaluator.java index 8cf1c6531e..fbec166683 100644 --- a/source/java/org/alfresco/repo/action/evaluator/IsSubTypeEvaluator.java +++ b/source/java/org/alfresco/repo/action/evaluator/IsSubTypeEvaluator.java @@ -91,10 +91,10 @@ public class IsSubTypeEvaluator extends ActionConditionEvaluatorAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_TYPE, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_TYPE))); } diff --git a/source/java/org/alfresco/repo/action/evaluator/NoConditionEvaluator.java b/source/java/org/alfresco/repo/action/evaluator/NoConditionEvaluator.java index 7ff73476b8..736b3dee52 100644 --- a/source/java/org/alfresco/repo/action/evaluator/NoConditionEvaluator.java +++ b/source/java/org/alfresco/repo/action/evaluator/NoConditionEvaluator.java @@ -43,10 +43,10 @@ public class NoConditionEvaluator extends ActionConditionEvaluatorAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { // No parameters to add } diff --git a/source/java/org/alfresco/repo/action/executer/ActionExecuterAbstractBase.java b/source/java/org/alfresco/repo/action/executer/ActionExecuterAbstractBase.java index 72f70ba498..ecce2db509 100644 --- a/source/java/org/alfresco/repo/action/executer/ActionExecuterAbstractBase.java +++ b/source/java/org/alfresco/repo/action/executer/ActionExecuterAbstractBase.java @@ -16,11 +16,15 @@ */ package org.alfresco.repo.action.executer; +import java.util.ArrayList; +import java.util.List; + import org.alfresco.repo.action.ActionDefinitionImpl; import org.alfresco.repo.action.ParameterizedItemAbstractBase; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ActionDefinition; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; /** * Rule action executor abstract base. @@ -38,6 +42,9 @@ public abstract class ActionExecuterAbstractBase extends ParameterizedItemAbstra * Indicated whether the action is public or internal */ protected boolean publicAction = true; + + /** List of types and aspects for which this action is applicable */ + protected List applicableTypes = new ArrayList(); /** * Init method @@ -59,6 +66,19 @@ public abstract class ActionExecuterAbstractBase extends ParameterizedItemAbstra { this.publicAction = publicAction; } + + /** + * Set the list of types for which this action is applicable + * + * @param applicableTypes arry of applicable types + */ + public void setApplicableTypes(String[] applicableTypes) + { + for (String type : applicableTypes) + { + this.applicableTypes.add(QName.createQName(type)); + } + } /** * Get rule action definition @@ -75,6 +95,7 @@ public abstract class ActionExecuterAbstractBase extends ParameterizedItemAbstra ((ActionDefinitionImpl)this.actionDefinition).setAdhocPropertiesAllowed(getAdhocPropertiesAllowed()); ((ActionDefinitionImpl)this.actionDefinition).setRuleActionExecutor(this.name); ((ActionDefinitionImpl)this.actionDefinition).setParameterDefinitions(getParameterDefintions()); + ((ActionDefinitionImpl)this.actionDefinition).setApplicableTypes(this.applicableTypes); } return this.actionDefinition; } diff --git a/source/java/org/alfresco/repo/action/executer/AddFeaturesActionExecuter.java b/source/java/org/alfresco/repo/action/executer/AddFeaturesActionExecuter.java index 557be6e6f1..13a8368083 100644 --- a/source/java/org/alfresco/repo/action/executer/AddFeaturesActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/AddFeaturesActionExecuter.java @@ -99,10 +99,10 @@ public class AddFeaturesActionExecuter extends ActionExecuterAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_ASPECT_NAME, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_ASPECT_NAME))); } diff --git a/source/java/org/alfresco/repo/action/executer/CheckInActionExecuter.java b/source/java/org/alfresco/repo/action/executer/CheckInActionExecuter.java index 366c97408c..be02ca7cef 100644 --- a/source/java/org/alfresco/repo/action/executer/CheckInActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/CheckInActionExecuter.java @@ -107,7 +107,7 @@ public class CheckInActionExecuter extends ActionExecuterAbstractBase } @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_DESCRIPTION, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_DESCRIPTION))); } diff --git a/source/java/org/alfresco/repo/action/executer/CheckOutActionExecuter.java b/source/java/org/alfresco/repo/action/executer/CheckOutActionExecuter.java index 16e5a5c45a..a00b62edfc 100644 --- a/source/java/org/alfresco/repo/action/executer/CheckOutActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/CheckOutActionExecuter.java @@ -74,7 +74,7 @@ public class CheckOutActionExecuter extends ActionExecuterAbstractBase * Add the parameter defintions */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_DESTINATION_FOLDER, DataTypeDefinition.NODE_REF, false, getParamDisplayLabel(PARAM_DESTINATION_FOLDER))); paramList.add(new ParameterDefinitionImpl(PARAM_ASSOC_TYPE_QNAME, DataTypeDefinition.QNAME, false, getParamDisplayLabel(PARAM_ASSOC_TYPE_QNAME))); diff --git a/source/java/org/alfresco/repo/action/executer/CompositeActionExecuter.java b/source/java/org/alfresco/repo/action/executer/CompositeActionExecuter.java index cf27a674fa..8ea3ecb357 100644 --- a/source/java/org/alfresco/repo/action/executer/CompositeActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/CompositeActionExecuter.java @@ -70,7 +70,7 @@ public class CompositeActionExecuter extends ActionExecuterAbstractBase * Add parameter definitions */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { // No parameters } diff --git a/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java b/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java index 91f220acec..66d29848e4 100644 --- a/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java +++ b/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java @@ -198,7 +198,7 @@ public class ContentMetadataExtracter extends ActionExecuterAbstractBase } @Override - protected void addParameterDefintions(List arg0) + protected void addParameterDefinitions(List arg0) { // None! } diff --git a/source/java/org/alfresco/repo/action/executer/CopyActionExecuter.java b/source/java/org/alfresco/repo/action/executer/CopyActionExecuter.java index a604312af4..1c1d92ebc4 100644 --- a/source/java/org/alfresco/repo/action/executer/CopyActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/CopyActionExecuter.java @@ -82,10 +82,10 @@ public class CopyActionExecuter extends ActionExecuterAbstractBase /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_DESTINATION_FOLDER, DataTypeDefinition.NODE_REF, true, getParamDisplayLabel(PARAM_DESTINATION_FOLDER))); paramList.add(new ParameterDefinitionImpl(PARAM_ASSOC_TYPE_QNAME, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_ASSOC_TYPE_QNAME))); diff --git a/source/java/org/alfresco/repo/action/executer/CreateVersionActionExecuter.java b/source/java/org/alfresco/repo/action/executer/CreateVersionActionExecuter.java index 78d367a6e1..91f543f1c2 100644 --- a/source/java/org/alfresco/repo/action/executer/CreateVersionActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/CreateVersionActionExecuter.java @@ -65,10 +65,10 @@ public class CreateVersionActionExecuter extends ActionExecuterAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { } diff --git a/source/java/org/alfresco/repo/action/executer/ExecuteAllRulesActionExecuter.java b/source/java/org/alfresco/repo/action/executer/ExecuteAllRulesActionExecuter.java index ab3cfefe15..2d9b0eb779 100644 --- a/source/java/org/alfresco/repo/action/executer/ExecuteAllRulesActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/ExecuteAllRulesActionExecuter.java @@ -143,10 +143,10 @@ public class ExecuteAllRulesActionExecuter extends ActionExecuterAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_EXECUTE_INHERITED_RULES, DataTypeDefinition.BOOLEAN, false, getParamDisplayLabel(PARAM_EXECUTE_INHERITED_RULES))); } diff --git a/source/java/org/alfresco/repo/action/executer/ExporterActionExecuter.java b/source/java/org/alfresco/repo/action/executer/ExporterActionExecuter.java index b5f0581c79..1dd2c196dd 100644 --- a/source/java/org/alfresco/repo/action/executer/ExporterActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/ExporterActionExecuter.java @@ -187,9 +187,9 @@ public class ExporterActionExecuter extends ActionExecuterAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_PACKAGE_NAME, DataTypeDefinition.TEXT, true, getParamDisplayLabel(PARAM_PACKAGE_NAME))); diff --git a/source/java/org/alfresco/repo/action/executer/ImageTransformActionExecuter.java b/source/java/org/alfresco/repo/action/executer/ImageTransformActionExecuter.java index a17defdf76..8d48b86a0e 100644 --- a/source/java/org/alfresco/repo/action/executer/ImageTransformActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/ImageTransformActionExecuter.java @@ -58,9 +58,9 @@ public class ImageTransformActionExecuter extends TransformActionExecuter * Add parameter definitions */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { - super.addParameterDefintions(paramList); + super.addParameterDefinitions(paramList); paramList.add(new ParameterDefinitionImpl(PARAM_CONVERT_COMMAND, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_CONVERT_COMMAND))); } diff --git a/source/java/org/alfresco/repo/action/executer/ImporterActionExecuter.java b/source/java/org/alfresco/repo/action/executer/ImporterActionExecuter.java index 172fde3f3f..10789a5a60 100644 --- a/source/java/org/alfresco/repo/action/executer/ImporterActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/ImporterActionExecuter.java @@ -134,9 +134,9 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_DESTINATION_FOLDER, DataTypeDefinition.NODE_REF, true, getParamDisplayLabel(PARAM_DESTINATION_FOLDER))); diff --git a/source/java/org/alfresco/repo/action/executer/LinkCategoryActionExecuter.java b/source/java/org/alfresco/repo/action/executer/LinkCategoryActionExecuter.java index d4af818515..88a96a15c4 100644 --- a/source/java/org/alfresco/repo/action/executer/LinkCategoryActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/LinkCategoryActionExecuter.java @@ -82,7 +82,7 @@ public class LinkCategoryActionExecuter extends ActionExecuterAbstractBase * Add the parameter definitions */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_CATEGORY_ASPECT, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_CATEGORY_ASPECT))); paramList.add(new ParameterDefinitionImpl(PARAM_CATEGORY_VALUE, DataTypeDefinition.NODE_REF, true, getParamDisplayLabel(PARAM_CATEGORY_VALUE))); diff --git a/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java b/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java index 8774040b8f..cc69f3bb64 100644 --- a/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java @@ -300,7 +300,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase * Add the parameter definitions */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_TO, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_TO))); paramList.add(new ParameterDefinitionImpl(PARAM_TO_MANY, DataTypeDefinition.ANY, false, getParamDisplayLabel(PARAM_TO_MANY))); diff --git a/source/java/org/alfresco/repo/action/executer/MoveActionExecuter.java b/source/java/org/alfresco/repo/action/executer/MoveActionExecuter.java index 0a339ad64d..25e7bf4c09 100644 --- a/source/java/org/alfresco/repo/action/executer/MoveActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/MoveActionExecuter.java @@ -51,7 +51,7 @@ public class MoveActionExecuter extends ActionExecuterAbstractBase } @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_DESTINATION_FOLDER, DataTypeDefinition.NODE_REF, true, getParamDisplayLabel(PARAM_DESTINATION_FOLDER))); paramList.add(new ParameterDefinitionImpl(PARAM_ASSOC_TYPE_QNAME, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_ASSOC_TYPE_QNAME))); diff --git a/source/java/org/alfresco/repo/action/executer/RemoveFeaturesActionExecuter.java b/source/java/org/alfresco/repo/action/executer/RemoveFeaturesActionExecuter.java index 1033a561b3..2fd5245460 100644 --- a/source/java/org/alfresco/repo/action/executer/RemoveFeaturesActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/RemoveFeaturesActionExecuter.java @@ -68,10 +68,10 @@ public class RemoveFeaturesActionExecuter extends ActionExecuterAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_ASPECT_NAME, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_ASPECT_NAME))); } diff --git a/source/java/org/alfresco/repo/action/executer/RepositoryExporterActionExecuter.java b/source/java/org/alfresco/repo/action/executer/RepositoryExporterActionExecuter.java index c6902c9e27..8d2f47cffe 100644 --- a/source/java/org/alfresco/repo/action/executer/RepositoryExporterActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/RepositoryExporterActionExecuter.java @@ -62,9 +62,9 @@ public class RepositoryExporterActionExecuter extends ActionExecuterAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_PACKAGE_NAME, DataTypeDefinition.TEXT, true, getParamDisplayLabel(PARAM_PACKAGE_NAME))); diff --git a/source/java/org/alfresco/repo/action/executer/ScriptActionExecutor.java b/source/java/org/alfresco/repo/action/executer/ScriptActionExecutor.java index 2b2515acb7..369b30911e 100644 --- a/source/java/org/alfresco/repo/action/executer/ScriptActionExecutor.java +++ b/source/java/org/alfresco/repo/action/executer/ScriptActionExecutor.java @@ -114,9 +114,9 @@ public class ScriptActionExecutor extends ActionExecuterAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_SCRIPTREF, DataTypeDefinition.NODE_REF, true, getParamDisplayLabel(PARAM_SCRIPTREF))); paramList.add(new ParameterDefinitionImpl(PARAM_SPACEREF, DataTypeDefinition.NODE_REF, false, getParamDisplayLabel(PARAM_SPACEREF))); diff --git a/source/java/org/alfresco/repo/action/executer/SetPropertyValueActionExecuter.java b/source/java/org/alfresco/repo/action/executer/SetPropertyValueActionExecuter.java index 0ce847616b..8bd920cce5 100644 --- a/source/java/org/alfresco/repo/action/executer/SetPropertyValueActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/SetPropertyValueActionExecuter.java @@ -74,7 +74,7 @@ public class SetPropertyValueActionExecuter extends ActionExecuterAbstractBase * Add parameter definitions */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_PROPERTY, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_PROPERTY))); paramList.add(new ParameterDefinitionImpl(PARAM_VALUE, DataTypeDefinition.ANY, true, getParamDisplayLabel(PARAM_VALUE))); diff --git a/source/java/org/alfresco/repo/action/executer/SimpleWorkflowActionExecuter.java b/source/java/org/alfresco/repo/action/executer/SimpleWorkflowActionExecuter.java index b317490b25..1e7309e846 100644 --- a/source/java/org/alfresco/repo/action/executer/SimpleWorkflowActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/SimpleWorkflowActionExecuter.java @@ -53,7 +53,7 @@ public class SimpleWorkflowActionExecuter extends ActionExecuterAbstractBase } @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_APPROVE_STEP, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_APPROVE_STEP))); paramList.add(new ParameterDefinitionImpl(PARAM_APPROVE_FOLDER, DataTypeDefinition.NODE_REF, false, getParamDisplayLabel(PARAM_APPROVE_FOLDER))); diff --git a/source/java/org/alfresco/repo/action/executer/SpecialiseTypeActionExecuter.java b/source/java/org/alfresco/repo/action/executer/SpecialiseTypeActionExecuter.java index 54912e4a06..377621939d 100644 --- a/source/java/org/alfresco/repo/action/executer/SpecialiseTypeActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/SpecialiseTypeActionExecuter.java @@ -92,10 +92,10 @@ public class SpecialiseTypeActionExecuter extends ActionExecuterAbstractBase } /** - * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_TYPE_NAME, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_TYPE_NAME))); } diff --git a/source/java/org/alfresco/repo/action/executer/TransformActionExecuter.java b/source/java/org/alfresco/repo/action/executer/TransformActionExecuter.java index a94828df59..8400ef1bbf 100644 --- a/source/java/org/alfresco/repo/action/executer/TransformActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/TransformActionExecuter.java @@ -123,7 +123,7 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase * Add parameter definitions */ @Override - protected void addParameterDefintions(List paramList) + protected void addParameterDefinitions(List paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_MIME_TYPE, DataTypeDefinition.TEXT, true, getParamDisplayLabel(PARAM_MIME_TYPE))); paramList.add(new ParameterDefinitionImpl(PARAM_DESTINATION_FOLDER, DataTypeDefinition.NODE_REF, true, getParamDisplayLabel(PARAM_DESTINATION_FOLDER))); diff --git a/source/java/org/alfresco/repo/dictionary/constraint/ConstraintsTest.java b/source/java/org/alfresco/repo/dictionary/constraint/ConstraintsTest.java index ec60f9c9a8..092e951209 100644 --- a/source/java/org/alfresco/repo/dictionary/constraint/ConstraintsTest.java +++ b/source/java/org/alfresco/repo/dictionary/constraint/ConstraintsTest.java @@ -38,6 +38,7 @@ import org.alfresco.service.cmr.dictionary.DictionaryException; * * @author Derek Hulley */ +@SuppressWarnings("unused") public class ConstraintsTest extends TestCase { @Override @@ -229,8 +230,8 @@ public class ConstraintsTest extends TestCase public void testRegexConstraintFilename() throws Exception { // we assume UTF-8 - String expression = ".*[\\\"\\*\\\\\\>\\<\\?\\/\\:\\|\\xA3\\xAC\\%\\&\\+\\;]+.*"; - String invalidChars = "\"*\\>\\<\\?\\/\\:\\|\\¬\\£\\%\\&\\+\\;]+.*".getBytes("UTF-8")); + String invalidChars = new String("\"*\\> getEntries(); + /** * Get inheritance behaviour - * @return + * @return Returns the inheritance status of this list */ public boolean getInherits(); /** * Set inheritance behaviour - * @param inherits + * @param inherits true to set the permissions to inherit */ public void setInherits(boolean inherits); + + public int deleteEntriesForAuthority(String authorityKey); + + public int deleteEntriesForPermission(DbPermissionKey permissionKey); + + public int deleteEntry(String authorityKey, DbPermissionKey permissionKey); /** * Delete the entries related to this access control list @@ -48,4 +64,18 @@ public interface DbAccessControlList * @return Returns the number of entries deleted */ public int deleteEntries(); + + public DbAccessControlEntry getEntry(String authorityKey, DbPermissionKey permissionKey); + + /** + * Factory method to create an entry and wire it up. + * Note that the returned value may still be transient. Saving it should be fine, but + * is not required. + * + * @param permission the mandatory permission association with this entry + * @param authority the mandatory authority. Must not be transient. + * @param allowed allowed or disallowed. Must not be transient. + * @return Returns the new entry + */ + public DbAccessControlEntryImpl newEntry(DbPermission permission, DbAuthority authority, boolean allowed); } diff --git a/source/java/org/alfresco/repo/domain/DbPermission.java b/source/java/org/alfresco/repo/domain/DbPermission.java index d1e741c2b5..5973c813ec 100644 --- a/source/java/org/alfresco/repo/domain/DbPermission.java +++ b/source/java/org/alfresco/repo/domain/DbPermission.java @@ -51,4 +51,10 @@ public interface DbPermission extends Serializable * @param name the name of the permission */ public void setName(String name); + + /** + * @return Returns a key combining the {@link #getTypeQname() type} + * and {@link #getName() name} + */ + public DbPermissionKey getKey(); } diff --git a/source/java/org/alfresco/repo/domain/DbPermissionKey.java b/source/java/org/alfresco/repo/domain/DbPermissionKey.java new file mode 100644 index 0000000000..654b37d8cd --- /dev/null +++ b/source/java/org/alfresco/repo/domain/DbPermissionKey.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.repo.domain; + +import java.io.Serializable; + +import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; + +/** + * Compound key for persistence of {@link org.alfresco.repo.domain.DbPermission}. + * + * @author Derek Hulley + */ +public class DbPermissionKey implements Serializable +{ + private static final long serialVersionUID = -1667797216480779296L; + + private QName typeQname; + private String name; + + public DbPermissionKey() + { + } + + public DbPermissionKey(QName typeQname, String name) + { + this.typeQname = typeQname; + this.name = name; + } + + public String toString() + { + return ("DbPermissionKey" + + "[ type=" + typeQname + + ", name=" + name + + "]"); + } + + public int hashCode() + { + return this.name.hashCode(); + } + + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + else if (!(obj instanceof DbPermissionKey)) + { + return false; + } + DbPermissionKey that = (DbPermissionKey) obj; + return (EqualsHelper.nullSafeEquals(this.typeQname, that.typeQname) + && EqualsHelper.nullSafeEquals(this.name, that.name) + ); + } + + public QName getTypeQname() + { + return typeQname; + } + + /** + * Tamper-proof method only to be used by introspectors + */ + @SuppressWarnings("unused") + private void setTypeQname(QName typeQname) + { + this.typeQname = typeQname; + } + + public String getName() + { + return name; + } + + /** + * Tamper-proof method only to be used by introspectors + */ + @SuppressWarnings("unused") + private void setName(String name) + { + this.name = name; + } +} diff --git a/source/java/org/alfresco/repo/domain/Node.java b/source/java/org/alfresco/repo/domain/Node.java index c85eb73e07..f988b5554d 100644 --- a/source/java/org/alfresco/repo/domain/Node.java +++ b/source/java/org/alfresco/repo/domain/Node.java @@ -80,5 +80,5 @@ public interface Node public DbAccessControlList getAccessControlList(); -// public void setAccessControlList(DbAccessControlList accessControlList); + public void setAccessControlList(DbAccessControlList accessControlList); } diff --git a/source/java/org/alfresco/repo/domain/hibernate/ChildAssocImpl.java b/source/java/org/alfresco/repo/domain/hibernate/ChildAssocImpl.java index 9f618b1ede..c32e0bf1b4 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/ChildAssocImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/ChildAssocImpl.java @@ -151,11 +151,12 @@ public class ChildAssocImpl implements ChildAssoc return false; } ChildAssoc that = (ChildAssoc) obj; - return (this.getIsPrimary() == that.getIsPrimary() - && EqualsHelper.nullSafeEquals(this.getTypeQName(), that.getTypeQName()) + return ( + EqualsHelper.nullSafeEquals(this.getTypeQName(), that.getTypeQName()) && EqualsHelper.nullSafeEquals(this.getQname(), that.getQname()) && EqualsHelper.nullSafeEquals(this.getParent(), that.getParent()) - && EqualsHelper.nullSafeEquals(this.getChild(), that.getChild())); + && EqualsHelper.nullSafeEquals(this.getChild(), that.getChild()) + ); } public int hashCode() diff --git a/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlEntryImpl.java b/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlEntryImpl.java index 88b2b76a0b..f9d67561dc 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlEntryImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlEntryImpl.java @@ -27,7 +27,7 @@ import org.alfresco.util.EqualsHelper; * * @author andyh */ -public class DbAccessControlEntryImpl implements DbAccessControlEntry +public class DbAccessControlEntryImpl extends LifecycleAdapter implements DbAccessControlEntry { /** The object id */ private long id; @@ -56,7 +56,7 @@ public class DbAccessControlEntryImpl implements DbAccessControlEntry sb.append("DbAccessControlEntryImpl") .append("[ id=").append(id) .append(", acl=").append(accessControlList.getId()) - .append(", permission=").append(permission.getId()) + .append(", permission=").append(permission.getKey()) .append(", authority=").append(authority.getRecipient()) .append("]"); return sb.toString(); @@ -74,16 +74,14 @@ public class DbAccessControlEntryImpl implements DbAccessControlEntry return false; } DbAccessControlEntry other = (DbAccessControlEntry) o; - return (this.allowed == other.isAllowed()) - && EqualsHelper.nullSafeEquals(this.accessControlList, other.getAccessControlList()) - && EqualsHelper.nullSafeEquals(this.permission, other.getPermission()) - && EqualsHelper.nullSafeEquals(this.authority, other.getAuthority()); + return (EqualsHelper.nullSafeEquals(this.permission, other.getPermission()) + && EqualsHelper.nullSafeEquals(this.authority, other.getAuthority())); } @Override public int hashCode() { - int hashCode = accessControlList.hashCode(); + int hashCode = 0; if (permission != null) { hashCode = hashCode * 37 + permission.hashCode(); @@ -92,33 +90,9 @@ public class DbAccessControlEntryImpl implements DbAccessControlEntry { hashCode = hashCode * 37 + authority.hashCode(); } - hashCode = hashCode * 37 + (allowed ? 1 : 0); return hashCode; } - - /** - * Factory method to create an entry and wire it in to the contained nodePermissionEntry - * - * @param accessControlList the list of entries that this one belongs to - * @param permission the mandatory permission association with this entry - * @param authority the mandatory authority - * @param allowed allowed or disallowed - * @return Returns an unpersisted entity - */ - public static DbAccessControlEntryImpl create( - DbAccessControlList accessControlList, - DbPermission permission, - DbAuthority authority, - boolean allowed) - { - DbAccessControlEntryImpl accessControlEntry = new DbAccessControlEntryImpl(); - accessControlEntry.setAccessControlList(accessControlList); - accessControlEntry.setPermission(permission); - accessControlEntry.setAuthority(authority); - accessControlEntry.setAllowed(allowed); - return accessControlEntry; - } - + public long getId() { return id; @@ -171,4 +145,13 @@ public class DbAccessControlEntryImpl implements DbAccessControlEntry { this.allowed = allowed; } + + public void delete() + { + // remove the instance from the access control list + @SuppressWarnings("unused") + boolean removed = getAccessControlList().getEntries().remove(this); + // delete the instance + getSession().delete(this); + } } diff --git a/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlListImpl.java b/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlListImpl.java index 06692722e7..4fa4f1725e 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlListImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlListImpl.java @@ -16,13 +16,20 @@ */ package org.alfresco.repo.domain.hibernate; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.alfresco.repo.domain.DbAccessControlEntry; import org.alfresco.repo.domain.DbAccessControlList; +import org.alfresco.repo.domain.DbAuthority; +import org.alfresco.repo.domain.DbPermission; +import org.alfresco.repo.domain.DbPermissionKey; import org.alfresco.repo.domain.Node; import org.alfresco.util.EqualsHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.hibernate.CallbackException; -import org.hibernate.Query; import org.hibernate.Session; /** @@ -36,8 +43,14 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces private long id; private Node node; + private Set entries; private boolean inherits; + public DbAccessControlListImpl() + { + entries = new HashSet(5); + } + @Override public String toString() { @@ -45,6 +58,7 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces sb.append("DbAccessControlListImpl") .append("[ id=").append(id) .append(", node=").append(node) + .append(", entries=").append(entries.size()) .append(", inherits=").append(inherits) .append("]"); return sb.toString(); @@ -73,35 +87,6 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces return (node == null ? 0 : node.hashCode()); } - public int deleteEntries() - { - /* - * This can use a delete direct to the database as well, but then care must be taken - * to evict the instances from the session. - */ - - // bypass L2 cache and get all entries for this list - Query query = getSession() - .getNamedQuery(PermissionsDaoComponentImpl.QUERY_GET_AC_ENTRIES_FOR_AC_LIST) - .setLong("accessControlListId", this.id); - int count = HibernateHelper.deleteQueryResults(getSession(), query); - // done - if (logger.isDebugEnabled()) - { - logger.debug("Deleted " + count + " access entries for access control list " + this.id); - } - return count; - } - - /** - * Ensures that all this access control list's entries have been deleted. - */ - public boolean onDelete(Session session) throws CallbackException - { - deleteEntries(); - return super.onDelete(session); - } - public long getId() { return id; @@ -126,9 +111,18 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces this.node = node; } - public DbAccessControlListImpl() + public Set getEntries() { - super(); + return entries; + } + + /** + * For Hibernate use + */ + @SuppressWarnings("unused") + private void setEntries(Set entries) + { + this.entries = entries; } public boolean getInherits() @@ -140,4 +134,112 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces { this.inherits = inherits; } + + /** + * @see #deleteEntry(String, DbPermissionKey) + */ + public int deleteEntriesForAuthority(String authority) + { + return deleteEntry(authority, null); + } + + /** + * @see #deleteEntry(String, DbPermissionKey) + */ + public int deleteEntriesForPermission(DbPermissionKey permissionKey) + { + return deleteEntry(null, permissionKey); + } + + public int deleteEntry(String authority, DbPermissionKey permissionKey) + { + List toDelete = new ArrayList(2); + for (DbAccessControlEntry entry : entries) + { + if (authority != null && !authority.equals(entry.getAuthority().getRecipient())) + { + // authority is not a match + continue; + } + else if (permissionKey != null && !permissionKey.equals(entry.getPermission().getKey())) + { + // permission is not a match + continue; + } + toDelete.add(entry); + } + // delete them + for (DbAccessControlEntry entry : toDelete) + { + // remove from the entry list + entry.delete(); + } + // done + if (logger.isDebugEnabled()) + { + logger.debug("Deleted " + toDelete.size() + " access entries: \n" + + " access control list: " + id + "\n" + + " authority: " + authority + "\n" + + " permission: " + permissionKey); + } + return toDelete.size(); + } + + public int deleteEntries() + { + /* + * We don't do the full delete-remove-from-set thing here. Just delete each child entity + * and then clear the entry set. + */ + + Session session = getSession(); + List toDelete = new ArrayList(entries); + // delete each entry + for (DbAccessControlEntry entry : toDelete) + { + session.delete(entry); + } + // clear the list + int count = entries.size(); + entries.clear(); + // done + if (logger.isDebugEnabled()) + { + logger.debug("Deleted " + count + " access entries for access control list " + this.id); + } + return count; + } + + public DbAccessControlEntry getEntry(String authority, DbPermissionKey permissionKey) + { + for (DbAccessControlEntry entry : entries) + { + DbAuthority authorityEntity = entry.getAuthority(); + DbPermission permissionEntity = entry.getPermission(); + // check for a match + if (authorityEntity.getRecipient().equals(authority) + && permissionEntity.getKey().equals(permissionKey)) + { + // found it + return entry; + } + } + return null; + } + + public DbAccessControlEntryImpl newEntry(DbPermission permission, DbAuthority authority, boolean allowed) + { + DbAccessControlEntryImpl accessControlEntry = new DbAccessControlEntryImpl(); + // fill + accessControlEntry.setAccessControlList(this); + accessControlEntry.setPermission(permission); + accessControlEntry.setAuthority(authority); + accessControlEntry.setAllowed(allowed); + // save it + getSession().save(accessControlEntry); + // maintain inverse set on the acl + getEntries().add(accessControlEntry); + // done + return accessControlEntry; + } } diff --git a/source/java/org/alfresco/repo/domain/hibernate/DbAuthorityImpl.java b/source/java/org/alfresco/repo/domain/hibernate/DbAuthorityImpl.java index 5194057763..9a793b80d0 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/DbAuthorityImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/DbAuthorityImpl.java @@ -38,11 +38,11 @@ public class DbAuthorityImpl extends LifecycleAdapter implements DbAuthority private static Log logger = LogFactory.getLog(DbAuthorityImpl.class); private String recipient; - private Set externalKeys = new HashSet(); + private Set externalKeys; public DbAuthorityImpl() { - super(); + externalKeys = new HashSet(); } @Override @@ -76,8 +76,8 @@ public class DbAuthorityImpl extends LifecycleAdapter implements DbAuthority // bypass L2 cache and get all entries for this list Query query = getSession() .getNamedQuery(PermissionsDaoComponentImpl.QUERY_GET_AC_ENTRIES_FOR_AUTHORITY) - .setString("recipient", this.recipient); - int count = HibernateHelper.deleteQueryResults(getSession(), query); + .setString("authorityRecipient", this.recipient); + int count = HibernateHelper.deleteDbAccessControlEntries(getSession(), query); // done if (logger.isDebugEnabled()) { @@ -115,4 +115,16 @@ public class DbAuthorityImpl extends LifecycleAdapter implements DbAuthority { this.externalKeys = externalKeys; } + + /** + * Helper method to find an authority based on its natural key + * + * @param session the Hibernate session to use + * @param authority the authority name + * @return Returns an existing instance or null if not found + */ + public static DbAuthority find(Session session, String authority) + { + return (DbAuthority) session.get(DbAuthorityImpl.class, authority); + } } diff --git a/source/java/org/alfresco/repo/domain/hibernate/DbPermissionImpl.java b/source/java/org/alfresco/repo/domain/hibernate/DbPermissionImpl.java index 1e270483db..501d7f419a 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/DbPermissionImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/DbPermissionImpl.java @@ -17,6 +17,7 @@ package org.alfresco.repo.domain.hibernate; import org.alfresco.repo.domain.DbPermission; +import org.alfresco.repo.domain.DbPermissionKey; import org.alfresco.service.namespace.QName; import org.alfresco.util.EqualsHelper; import org.apache.commons.logging.Log; @@ -90,7 +91,7 @@ public class DbPermissionImpl extends LifecycleAdapter implements DbPermission Query query = getSession() .getNamedQuery(PermissionsDaoComponentImpl.QUERY_GET_AC_ENTRIES_FOR_PERMISSION) .setSerializable("permissionId", this.id); - int count = HibernateHelper.deleteQueryResults(getSession(), query); + int count = HibernateHelper.deleteDbAccessControlEntries(getSession(), query); // done if (logger.isDebugEnabled()) { @@ -142,6 +143,11 @@ public class DbPermissionImpl extends LifecycleAdapter implements DbPermission this.name = name; } + public DbPermissionKey getKey() + { + return new DbPermissionKey(typeQname, name); + } + /** * Helper method to find a permission based on its natural key * diff --git a/source/java/org/alfresco/repo/domain/hibernate/HibernateHelper.java b/source/java/org/alfresco/repo/domain/hibernate/HibernateHelper.java index 86070d90a8..8da807a8fe 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/HibernateHelper.java +++ b/source/java/org/alfresco/repo/domain/hibernate/HibernateHelper.java @@ -16,8 +16,7 @@ */ package org.alfresco.repo.domain.hibernate; -import org.hibernate.CacheMode; -import org.hibernate.ObjectDeletedException; +import org.alfresco.repo.domain.DbAccessControlEntry; import org.hibernate.Query; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; @@ -32,36 +31,25 @@ public class HibernateHelper { /** * Helper method to scroll through the results of a query and delete all the - * results, performing batch flushes. This will handle large resultsets by - * pulling the results directly in from the query. For certain circumstances, it - * may be better to perform a bulk delete directly instead. + * resulting access control entries, performing batch flushes. * * @param session the session to use for the deletions - * @param query the query with all parameters set - * @return Returns the number of entities deleted, regardless of type + * @param query the query with all parameters set and that will return + * {@link org.alfresco.repo.domain.DbAccessControlEntry access control entry} instances + * @return Returns the number of entries deleted */ - public static int deleteQueryResults(Session session, Query query) + public static int deleteDbAccessControlEntries(Session session, Query query) { - ScrollableResults entities = query.setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY); + ScrollableResults entities = query.scroll(ScrollMode.FORWARD_ONLY); int count = 0; while (entities.next()) { - Object[] entityResults = entities.get(); - for (Object object : entityResults) + DbAccessControlEntry entry = (DbAccessControlEntry) entities.get(0); + entry.delete(); + if (++count % 50 == 0) { - try - { - session.delete(object); - } - catch (ObjectDeletedException e) - { - // ignore - it's what we wanted - } - if (++count % 50 == 0) - { - session.flush(); - session.clear(); - } + session.flush(); + session.clear(); } } return count; diff --git a/source/java/org/alfresco/repo/domain/hibernate/LifecycleAdapter.java b/source/java/org/alfresco/repo/domain/hibernate/LifecycleAdapter.java index 54c202accc..7e9740809c 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/LifecycleAdapter.java +++ b/source/java/org/alfresco/repo/domain/hibernate/LifecycleAdapter.java @@ -18,6 +18,7 @@ package org.alfresco.repo.domain.hibernate; import java.io.Serializable; +import org.alfresco.error.AlfrescoRuntimeException; import org.hibernate.CallbackException; import org.hibernate.Session; import org.hibernate.classic.Lifecycle; @@ -37,6 +38,10 @@ public abstract class LifecycleAdapter implements Lifecycle */ protected Session getSession() { + if (session == null) + { + throw new AlfrescoRuntimeException("Hibernate entity is not part of a session: " + this); + } return session; } diff --git a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml index 0701924b99..b02a880151 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml @@ -28,9 +28,9 @@ name="store" class="org.alfresco.repo.domain.hibernate.StoreImpl" not-null="true" - lazy="no-proxy" + lazy="proxy" optimistic-lock="true" - fetch="select"> + fetch="join"> @@ -43,8 +43,8 @@ name="accessControlList" class="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl" property-ref="node" - lazy="no-proxy" - fetch="select" + lazy="false" + fetch="join" cascade="delete" /> - + optimistic-lock="true" > - + - + optimistic-lock="true" > - + - - + - - + + unique="false" + not-null="false" /> @@ -165,10 +169,6 @@ - - - - + + + + - - - - - - - - - + + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/domain/hibernate/NodeImpl.java b/source/java/org/alfresco/repo/domain/hibernate/NodeImpl.java index df770553b8..856efe02e5 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/NodeImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/NodeImpl.java @@ -16,7 +16,6 @@ */ package org.alfresco.repo.domain.hibernate; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -34,6 +33,7 @@ import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.domain.Store; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; /** * Bean containing all the persistence data representing a node. @@ -65,10 +65,10 @@ public class NodeImpl extends LifecycleAdapter implements Node public NodeImpl() { aspects = new HashSet(5); - sourceNodeAssocs = new ArrayList(3); - targetNodeAssocs = new ArrayList(3); - parentAssocs = new ArrayList(3); - childAssocs = new ArrayList(3); + sourceNodeAssocs = new HashSet(5); + targetNodeAssocs = new HashSet(5); + parentAssocs = new HashSet(5); + childAssocs = new HashSet(11); properties = new HashMap(5); ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); @@ -134,12 +134,13 @@ public class NodeImpl extends LifecycleAdapter implements Node return false; } Node that = (Node) obj; - return (this.getNodeRef().equals(that.getNodeRef())); + return (EqualsHelper.nullSafeEquals(getStore(), that.getStore()) + && EqualsHelper.nullSafeEquals(getUuid(), that.getUuid())); } public int hashCode() { - return getNodeRef().hashCode(); + return getUuid().hashCode(); } // @Override @@ -316,11 +317,7 @@ public class NodeImpl extends LifecycleAdapter implements Node return accessControlList; } - /** - * For Hibernate use - */ - @SuppressWarnings("unused") - private void setAccessControlList(DbAccessControlList accessControlList) + public void setAccessControlList(DbAccessControlList accessControlList) { this.accessControlList = accessControlList; } diff --git a/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml index f4032016f1..9d72a4fe85 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml @@ -26,6 +26,16 @@ not-null="true"> + + + + + @@ -47,29 +57,29 @@ + name="accessControlList" + class="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl" + column="acl_id" + lazy="no-proxy" + fetch="select" + optimistic-lock="true" + not-null="true" /> + name="permission" + class="org.alfresco.repo.domain.hibernate.DbPermissionImpl" + column="permission_id" + lazy="no-proxy" + fetch="select" + optimistic-lock="true" + not-null="true" /> + name="authority" + class="org.alfresco.repo.domain.hibernate.DbAuthorityImpl" + column="authority_id" + lazy="no-proxy" + fetch="select" + optimistic-lock="true" + not-null="true" /> @@ -83,7 +93,7 @@ dynamic-insert="false" dynamic-update="false" select-before-update="false" - lazy="true" + lazy="false" optimistic-lock="version" > @@ -104,7 +114,7 @@ dynamic-insert="false" dynamic-update="false" select-before-update="false" - lazy="true" + lazy="false" optimistic-lock="version" > @@ -133,24 +143,6 @@ permission.name = :permissionName - - select - ace - from - org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl as ace - where - ace.accessControlList.id = :accessControlListId - - - - select - ace - from - org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl as ace - where - ace.permission.id = :permissionId - - select ace @@ -160,41 +152,4 @@ ace.authority.recipient = :authorityRecipient - - select - ace - from - org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl as ace - where - ace.authority.recipient = :authorityRecipient and - ace.accessControlList.node.store.key.protocol = :storeProtocol and - ace.accessControlList.node.store.key.identifier = :storeIdentifier and - ace.accessControlList.node.uuid = :nodeUuid - - - - select - ace - from - org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl as ace - where - ace.permission.typeQname = :permissionTypeQName and - ace.permission.name = :permissionName and - ace.authority.recipient = :authorityRecipient and - ace.accessControlList.node.store.key.protocol = :storeProtocol and - ace.accessControlList.node.store.key.identifier = :storeIdentifier and - ace.accessControlList.node.uuid = :nodeUuid - - - - select - acl - from - org.alfresco.repo.domain.hibernate.DbAccessControlListImpl as acl - where - acl.node.store.key.protocol = :storeProtocol and - acl.node.store.key.identifier = :storeIdentifier and - acl.node.uuid = :nodeUuid - - \ No newline at end of file diff --git a/source/java/org/alfresco/repo/domain/hibernate/PermissionsDaoComponentImpl.java b/source/java/org/alfresco/repo/domain/hibernate/PermissionsDaoComponentImpl.java index 8dc7a42357..18d2dbfc06 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/PermissionsDaoComponentImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/PermissionsDaoComponentImpl.java @@ -16,16 +16,16 @@ */ package org.alfresco.repo.domain.hibernate; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Set; -import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.domain.DbAccessControlEntry; import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.domain.DbAuthority; import org.alfresco.repo.domain.DbPermission; +import org.alfresco.repo.domain.DbPermissionKey; import org.alfresco.repo.domain.Node; import org.alfresco.repo.node.db.NodeDaoService; import org.alfresco.repo.security.permissions.NodePermissionEntry; @@ -55,16 +55,12 @@ import org.springframework.orm.hibernate3.support.HibernateDaoSupport; */ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements PermissionsDaoComponent { + private static final boolean INHERIT_PERMISSIONS_DEFAULT = true; public static final String QUERY_GET_PERMISSION = "permission.GetPermission"; - public static final String QUERY_GET_AC_LIST_FOR_NODE = "permission.GetAccessControlListForNode"; - public static final String QUERY_GET_AC_ENTRIES_FOR_AC_LIST = "permission.GetAccessControlEntriesForAccessControlList"; public static final String QUERY_GET_AC_ENTRIES_FOR_AUTHORITY = "permission.GetAccessControlEntriesForAuthority"; public static final String QUERY_GET_AC_ENTRIES_FOR_PERMISSION = "permission.GetAccessControlEntriesForPermission"; - public static final String QUERY_GET_AC_ENTRIES_FOR_AUTHORITY_AND_NODE = "permission.GetAccessControlEntriesForAuthorityAndNode"; - public static final String QUERY_GET_AC_ENTRY_FOR_ALL = "permission.GetAccessControlEntryForAll"; private NodeDaoService nodeDaoService; - private SimpleCache nullPermissionCache; public PermissionsDaoComponentImpl() { @@ -76,11 +72,6 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements this.nodeDaoService = nodeDaoService; } - public void setNullPermissionCache(SimpleCache nullPermissionCache) - { - this.nullPermissionCache = nullPermissionCache; - } - public NodePermissionEntry getPermissions(NodeRef nodeRef) { // Create the object if it is not found. @@ -88,20 +79,22 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements // If the object does not exist it will repeatedly query to check its // non existence. - NodePermissionEntry npe = nullPermissionCache.get(nodeRef); - if (npe != null) + NodePermissionEntry npe = null; + DbAccessControlList acl = null; + Node node = getNode(nodeRef, false); + if (node != null) { - return npe; + // get the persisted version + acl = getAccessControlList(node, false); } - // get the persisted version - DbAccessControlList acl = getAccessControlList(nodeRef, false); if (acl == null) { // there isn't an access control list for the node - spoof a null one SimpleNodePermissionEntry snpe = new SimpleNodePermissionEntry( - nodeRef, true, Collections. emptySet()); + nodeRef, + true, + Collections. emptySet()); npe = snpe; - nullPermissionCache.put(nodeRef, snpe); } else { @@ -122,46 +115,18 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements * @param create - create the object if it is missing * @return Returns the current access control list or null if not found */ - private DbAccessControlList getAccessControlList(final NodeRef nodeRef, boolean create) + private DbAccessControlList getAccessControlList(Node node, boolean create) { - // get the access control list for the node - HibernateCallback callback = new HibernateCallback() + DbAccessControlList acl = node.getAccessControlList(); + if (acl == null && create) { - public Object doInHibernate(Session session) - { - Query query = session.getNamedQuery(PermissionsDaoComponentImpl.QUERY_GET_AC_LIST_FOR_NODE); - query.setString("storeProtocol", nodeRef.getStoreRef().getProtocol()) - .setString("storeIdentifier", nodeRef.getStoreRef().getIdentifier()) - .setString("nodeUuid", nodeRef.getId()); - return query.list(); - } - }; - @SuppressWarnings("unchecked") - List results = (List) getHibernateTemplate().execute(callback); - DbAccessControlList acl = null; - if (results.size() == 0) - { - // create it - if (create) - { - acl = createAccessControlList(nodeRef); - } - // else null will be returned - } - else if (results.size() > 0) - { - acl = (DbAccessControlList) results.get(0); - } - else if (results.size() > 1) - { - logger.warn("Duplicate access control lists for node: " + nodeRef); - acl = (DbAccessControlList) results.get(0); + acl = createAccessControlList(node); } // done if (logger.isDebugEnabled()) { logger.debug("Retrieved access control list: \n" + - " node: " + nodeRef + "\n" + + " node: " + node.getNodeRef() + "\n" + " list: " + acl); } return acl; @@ -171,17 +136,17 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements * Creates an access control list for the node and removes the entry from * the nullPermsionCache. */ - private DbAccessControlList createAccessControlList(final NodeRef nodeRef) + private DbAccessControlList createAccessControlList(Node node) { - // get the node referenced - Node node = getNode(nodeRef); - DbAccessControlList acl = new DbAccessControlListImpl(); acl.setNode(node); - acl.setInherits(true); + acl.setInherits(INHERIT_PERMISSIONS_DEFAULT); getHibernateTemplate().save(acl); - nullPermissionCache.remove(nodeRef); + // maintain inverse + node.setAccessControlList(acl); + + NodeRef nodeRef = node.getNodeRef(); // done if (logger.isDebugEnabled()) @@ -195,12 +160,14 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements /** * @param nodeRef the node reference - * @return Returns the node for the given reference, or null + * @param mustExist true if an exception must be thrown if the node does not exist + * @return Returns the node for the given reference, or null if mustExist == false + * @throws InvalidNodeRefException if the node must exist but doesn't */ - private Node getNode(NodeRef nodeRef) + private Node getNode(NodeRef nodeRef, boolean mustExist) { Node node = nodeDaoService.getNode(nodeRef); - if (node == null) + if (node == null && mustExist) { throw new InvalidNodeRefException(nodeRef); } @@ -209,17 +176,25 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements public void deletePermissions(NodeRef nodeRef) { - DbAccessControlList acl = getAccessControlList(nodeRef, false); + Node node = getNode(nodeRef, false); + if (node == null) + { + return; + } + DbAccessControlList acl = getAccessControlList(node, false); if (acl != null) { // delete the access control list - it will cascade to the entries getHibernateTemplate().delete(acl); + // maintain inverse + node.setAccessControlList(null); } } @SuppressWarnings("unchecked") public void deletePermissions(final String authority) { + // get the authority HibernateCallback callback = new HibernateCallback() { public Object doInHibernate(Session session) @@ -227,7 +202,7 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements Query query = session .getNamedQuery(QUERY_GET_AC_ENTRIES_FOR_AUTHORITY) .setString("authorityRecipient", authority); - return (Integer) HibernateHelper.deleteQueryResults(session, query); + return (Integer) HibernateHelper.deleteDbAccessControlEntries(session, query); } }; Integer deletedCount = (Integer) getHibernateTemplate().execute(callback); @@ -240,20 +215,17 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements public void deletePermissions(final NodeRef nodeRef, final String authority) { - HibernateCallback callback = new HibernateCallback() + Node node = getNode(nodeRef, false); + if (node == null) { - public Object doInHibernate(Session session) - { - Query query = session - .getNamedQuery(QUERY_GET_AC_ENTRIES_FOR_AUTHORITY_AND_NODE) - .setString("authorityRecipient", authority) - .setString("storeProtocol", nodeRef.getStoreRef().getProtocol()) - .setString("storeIdentifier", nodeRef.getStoreRef().getIdentifier()) - .setString("nodeUuid", nodeRef.getId()); - return HibernateHelper.deleteQueryResults(session, query); - } - }; - Integer deletedCount = (Integer) getHibernateTemplate().execute(callback); + return; + } + DbAccessControlList acl = node.getAccessControlList(); + int deletedCount = 0; + if (acl != null) + { + deletedCount = acl.deleteEntriesForAuthority(authority); + } // done if (logger.isDebugEnabled()) { @@ -268,40 +240,43 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements * the given criteria. Note that the access control list for the node is * not deleted. */ - public void deletePermission(final NodeRef nodeRef, final String authority, final PermissionReference permission) + public void deletePermission(NodeRef nodeRef, String authority, PermissionReference permission) { - // get the entry - DbAccessControlEntry entry = getAccessControlEntry(nodeRef, authority, permission); - if (entry != null) + Node node = getNode(nodeRef, false); + if (node == null) { - getHibernateTemplate().delete(entry); - // done - if (logger.isDebugEnabled()) - { - logger.debug("Deleted entry for criteria: \n" + - " node: " + nodeRef + "\n" + - " authority: " + authority + "\n" + - " permission: " + permission); - } + return; + } + DbAccessControlList acl = node.getAccessControlList(); + int deletedCount = 0; + if (acl != null) + { + DbPermissionKey permissionKey = new DbPermissionKey(permission.getQName(), permission.getName()); + deletedCount = acl.deleteEntry(authority, permissionKey); + } + // done + if (logger.isDebugEnabled()) + { + logger.debug("Deleted " + deletedCount + "entries for criteria: \n" + + " node: " + nodeRef + "\n" + + " permission: " + permission + "\n" + + " authority: " + authority); } } public void setPermission(NodeRef nodeRef, String authority, PermissionReference permission, boolean allow) { + Node node = getNode(nodeRef, true); // get the entry - DbAccessControlEntry entry = getAccessControlEntry(nodeRef, authority, permission); + DbAccessControlEntry entry = getAccessControlEntry(node, authority, permission); if (entry == null) { // need to create it - DbAccessControlList dbAccessControlList = getAccessControlList(nodeRef, true); + DbAccessControlList dbAccessControlList = getAccessControlList(node, true); DbPermission dbPermission = getPermission(permission, true); DbAuthority dbAuthority = getAuthority(authority, true); // set persistent objects - entry = DbAccessControlEntryImpl.create(dbAccessControlList, dbPermission, dbAuthority, allow); - // save it - getHibernateTemplate().save(entry); - // drop the entry from the null cache - nullPermissionCache.remove(nodeRef); + entry = dbAccessControlList.newEntry(dbPermission, dbAuthority, allow); // done if (logger.isDebugEnabled()) { @@ -326,31 +301,22 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements * @return Returns all access control entries that match the criteria */ private DbAccessControlEntry getAccessControlEntry( - final NodeRef nodeRef, - final String authority, - final PermissionReference permission) + Node node, + String authority, + PermissionReference permission) { - HibernateCallback callback = new HibernateCallback() + DbAccessControlList acl = getAccessControlList(node, false); + DbAccessControlEntry entry = null; + if (acl != null) { - public Object doInHibernate(Session session) - { - Query query = session - .getNamedQuery(QUERY_GET_AC_ENTRY_FOR_ALL) - .setString("permissionTypeQName", permission.getQName().toString()) - .setString("permissionName", permission.getName()) - .setString("authorityRecipient", authority) - .setString("storeProtocol", nodeRef.getStoreRef().getProtocol()) - .setString("storeIdentifier", nodeRef.getStoreRef().getIdentifier()) - .setString("nodeUuid", nodeRef.getId()); - return (DbAccessControlEntry) query.uniqueResult(); - } - }; - DbAccessControlEntry entry = (DbAccessControlEntry) getHibernateTemplate().execute(callback); + DbPermissionKey permissionKey = new DbPermissionKey(permission.getQName(), permission.getName()); + entry = acl.getEntry(authority, permissionKey); + } // done if (logger.isDebugEnabled()) { logger.debug("" + (entry == null ? "Did not find" : "Found") + "entry for criteria: \n" + - " node: " + nodeRef + "\n" + + " node: " + node.getId() + "\n" + " authority: " + authority + "\n" + " permission: " + permission); } @@ -383,15 +349,9 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements { final QName qname = permissionRef.getQName(); final String name = permissionRef.getName(); + Session session = getSession(); - HibernateCallback callback = new HibernateCallback() - { - public Object doInHibernate(Session session) - { - return DbPermissionImpl.find(session, qname, name); - } - }; - DbPermission dbPermission = (DbPermission) getHibernateTemplate().execute(callback); + DbPermission dbPermission = DbPermissionImpl.find(session, qname, name); // create if necessary if ((dbPermission == null) && create) @@ -416,24 +376,21 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements public void setPermission(NodePermissionEntry nodePermissionEntry) { NodeRef nodeRef = nodePermissionEntry.getNodeRef(); - // get the access control list - DbAccessControlList acl = getAccessControlList(nodeRef, false); - if (acl == null) + Node node = getNode(nodeRef, true); + + // Get the access control list + // Note the logic here requires to know whether it was created or not + DbAccessControlList acl = getAccessControlList(node, false); + if (acl != null) { - // create the access control list - acl = createAccessControlList(nodeRef); - } - else - { - // remove entries associated with the list - int deleted = acl.deleteEntries(); - if (logger.isDebugEnabled()) - { - logger.debug("Deleted " + deleted + " entries for access control list: \n" + - " acl: " + acl); - } - getSession().flush(); + // drop the list + getHibernateTemplate().delete(acl); + // update node + node.setAccessControlList(null); } + // create the access control list + acl = createAccessControlList(node); + // set attributes acl.setInherits(nodePermissionEntry.inheritPermissions()); @@ -447,24 +404,41 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements DbPermission permissionEntity = getPermission(permission, true); DbAuthority authorityEntity = getAuthority(authority, true); - DbAccessControlEntryImpl entry = DbAccessControlEntryImpl.create( - acl, - permissionEntity, - authorityEntity, - isAllowed); - getHibernateTemplate().save(entry); + @SuppressWarnings("unused") + DbAccessControlEntryImpl entry = acl.newEntry(permissionEntity, authorityEntity, isAllowed); } } public void setInheritParentPermissions(NodeRef nodeRef, boolean inheritParentPermissions) { - DbAccessControlList acl = getAccessControlList(nodeRef, true); - acl.setInherits(inheritParentPermissions); + Node node = getNode(nodeRef, true); + + DbAccessControlList acl = null; + if (!inheritParentPermissions) + { + // Inheritance == true is the default, so only force a create of the ACL if the value false + acl = getAccessControlList(node, true); + acl.setInherits(false); + } + else + { + acl = getAccessControlList(node, false); + if (acl != null) + { + acl.setInherits(true); + } + } } public boolean getInheritParentPermissions(NodeRef nodeRef) { - DbAccessControlList acl = getAccessControlList(nodeRef, false); + Node node = getNode(nodeRef, false); + if (node == null) + { + return INHERIT_PERMISSIONS_DEFAULT; + } + + DbAccessControlList acl = getAccessControlList(node, false); if (acl == null) { return true; @@ -484,46 +458,19 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements { ParameterCheck.mandatory("acl", acl); } - List entries = getEntriesForList(acl); + Set entries = acl.getEntries(); SimpleNodePermissionEntry snpe = new SimpleNodePermissionEntry( acl.getNode().getNodeRef(), acl.getInherits(), createSimplePermissionEntries(entries)); return snpe; } - - /** - * Executes a query to retrieve the access control list's entries - * - * @param acl the access control list - * @return Returns a list of the entries - */ - @SuppressWarnings("unchecked") - private List getEntriesForList(final DbAccessControlList acl) - { - HibernateCallback callback = new HibernateCallback() - { - public Object doInHibernate(Session session) - { - Query query = session.getNamedQuery(QUERY_GET_AC_ENTRIES_FOR_AC_LIST); - query.setLong("accessControlListId", acl.getId()); - return query.list(); - } - }; - List entries = (List) getHibernateTemplate().execute(callback); - // done - if (logger.isDebugEnabled()) - { - logger.debug("Found " + entries.size() + " entries for access control list " + acl.getId()); - } - return entries; - } /** * @param entries access control entries * @return Returns a unique set of entries that can be given back to the outside world */ - private Set createSimplePermissionEntries(List entries) + private Set createSimplePermissionEntries(Collection entries) { if (entries == null) { diff --git a/source/java/org/alfresco/repo/domain/hibernate/Store.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Store.hbm.xml index 07da354377..6691a9937a 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/Store.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/Store.hbm.xml @@ -23,9 +23,9 @@ + fetch="select" > diff --git a/source/java/org/alfresco/repo/domain/hibernate/StoreImpl.java b/source/java/org/alfresco/repo/domain/hibernate/StoreImpl.java index 1a700a588e..c469858bd4 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/StoreImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/StoreImpl.java @@ -123,7 +123,7 @@ public class StoreImpl implements Store return key; } - public synchronized void setKey(StoreKey key) + public void setKey(StoreKey key) { refWriteLock.lock(); try diff --git a/source/java/org/alfresco/repo/importer/FileImporterTest.java b/source/java/org/alfresco/repo/importer/FileImporterTest.java index 746e8a0ee4..30fa98a608 100644 --- a/source/java/org/alfresco/repo/importer/FileImporterTest.java +++ b/source/java/org/alfresco/repo/importer/FileImporterTest.java @@ -49,7 +49,6 @@ import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.ApplicationContextHelper; -import org.alfresco.util.TempFileProvider; import org.alfresco.util.TestWithUserUtils; import org.springframework.context.ApplicationContext; @@ -196,10 +195,6 @@ public class FileImporterTest extends TestCase String userPwd = args.length > 6 ? args[6] : ""; while (count < target) { - File directory = TempFileProvider.getTempDir(); - File[] files = directory.listFiles(); - System.out.println("Start temp file count = " + files.length); - count++; FileImporterTest test = new FileImporterTest(); test.setUp(); @@ -268,15 +263,9 @@ public class FileImporterTest extends TestCase System.out.println("Committed in: " + ((end - start) / 1000000.0) + "ms"); double total = ((first+second)/1000000.0); System.out.println("Grand Total: "+ grandTotal); - System.out.println("Count: "+ count + "ms"); System.out.println("Imported: " + importCount + " files or directories"); System.out.println("Average: " + (importCount / (total / 1000.0)) + " files per second"); - directory = TempFileProvider.getTempDir(); - files = directory.listFiles(); - System.out.println("End temp file count = " + files.length); - - tx = transactionService.getUserTransaction(); tx.begin(); SearchParameters sp = new SearchParameters(); diff --git a/source/java/org/alfresco/repo/node/archive/ArchiveAndRestoreTest.java b/source/java/org/alfresco/repo/node/archive/ArchiveAndRestoreTest.java index 9ba9c0640d..f74b8bfabe 100644 --- a/source/java/org/alfresco/repo/node/archive/ArchiveAndRestoreTest.java +++ b/source/java/org/alfresco/repo/node/archive/ArchiveAndRestoreTest.java @@ -165,11 +165,11 @@ public class ArchiveAndRestoreTest extends TestCase * Create the following: *
      *        root
-     *       /  |  \
-     *      /   |   \
-     *     /    |    \
-     *    /     |     \
-     *   A  <-> B      X
+     *       /  |
+     *      /   |
+     *     /    |
+     *    /     |
+     *   A  <-> B
      *   |\    /|
      *   | \  / |
      *   |  \/  |
@@ -500,6 +500,17 @@ public class ArchiveAndRestoreTest extends TestCase
         txn.begin();
     }
     
+    public void testRestoreToMissingParent() throws Exception
+    {
+        nodeService.deleteNode(a);
+        nodeService.deleteNode(b);
+        commitAndBeginNewTransaction();
+        
+        // attempt to restore b_ to a
+        RestoreNodeReport report = nodeArchiveService.restoreArchivedNode(b_, a, null, null);
+        assertEquals("Incorrect report status", RestoreStatus.FAILURE_INVALID_PARENT, report.getStatus());
+    }
+    
     public void testMassRestore() throws Exception
     {
         nodeService.deleteNode(a);
diff --git a/source/java/org/alfresco/repo/node/archive/NodeArchiveServiceImpl.java b/source/java/org/alfresco/repo/node/archive/NodeArchiveServiceImpl.java
index 40a3334b07..0fc0f48441 100644
--- a/source/java/org/alfresco/repo/node/archive/NodeArchiveServiceImpl.java
+++ b/source/java/org/alfresco/repo/node/archive/NodeArchiveServiceImpl.java
@@ -21,8 +21,10 @@ import java.util.List;
 
 import org.alfresco.model.ContentModel;
 import org.alfresco.repo.node.archive.RestoreNodeReport.RestoreStatus;
+import org.alfresco.repo.security.permissions.AccessDeniedException;
 import org.alfresco.repo.transaction.TransactionUtil;
 import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
+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;
@@ -133,13 +135,34 @@ public class NodeArchiveServiceImpl implements NodeArchiveService
             {
                 report.setStatus(RestoreStatus.FAILURE_INVALID_PARENT);
             }
+            else if (destinationNodeRef == null)
+            {
+                // get the original parent of the archived node
+                ChildAssociationRef originalParentAssocRef = (ChildAssociationRef) nodeService.getProperty(
+                        archivedNodeRef,
+                        ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC);
+                NodeRef originalParentNodeRef = originalParentAssocRef.getParentRef();
+                if (EqualsHelper.nullSafeEquals(originalParentNodeRef, invalidNodeRef))
+                {
+                    report.setStatus(RestoreStatus.FAILURE_INVALID_PARENT);
+                }
+                else
+                {
+                    // some other invalid node was detected
+                    report.setStatus(RestoreStatus.FAILURE_OTHER);
+                }
+            }
             else
             {
                 // some other invalid node was detected
                 report.setStatus(RestoreStatus.FAILURE_OTHER);
             }
         }
-        // TODO: Catch permission exceptions
+        catch (AccessDeniedException e)
+        {
+            report.setCause(e);
+            report.setStatus(RestoreStatus.FAILURE_PERMISSION);
+        }
         catch (Throwable e)
         {
             report.setCause(e);
diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
index 998f60ab8c..53dbdefca2 100644
--- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
+++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
@@ -409,19 +409,24 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
         // get the old parent
         Node oldParentNode = oldAssoc.getParent();
         
-        // Invoke policy behaviour
-        invokeBeforeDeleteChildAssociation(oldAssocRef);
-        invokeBeforeCreateChildAssociation(newParentRef, nodeToMoveRef, assocTypeQName, assocQName);
-        invokeBeforeUpdateNode(oldParentNode.getNodeRef());    // old parent will be updated
-        invokeBeforeUpdateNode(newParentRef);                  // new parent ditto
+        boolean movingStore = !nodeToMoveRef.getStoreRef().equals(newParentRef.getStoreRef());
         
-        // If the node is moving stores, then drag the node hierarchy with it
-        if (!nodeToMoveRef.getStoreRef().equals(newParentRef.getStoreRef()))
+        // data needed for policy invocation
+        QName nodeToMoveTypeQName = nodeToMove.getTypeQName();
+        Set nodeToMoveAspects = nodeToMove.getAspects();
+
+        // Invoke policy behaviour
+        if (movingStore)
         {
-            Store newStore = newParentNode.getStore();
-            moveNodeToStore(nodeToMove, newStore);
-            // the node reference will have changed too
-            nodeToMoveRef = nodeToMove.getNodeRef();
+            invokeBeforeDeleteNode(nodeToMoveRef);
+            invokeBeforeCreateNode(newParentRef, assocTypeQName, assocQName, nodeToMoveTypeQName);
+        }
+        else
+        {
+            invokeBeforeDeleteChildAssociation(oldAssocRef);
+            invokeBeforeCreateChildAssociation(newParentRef, nodeToMoveRef, assocTypeQName, assocQName);
+            invokeBeforeUpdateNode(oldParentNode.getNodeRef());    // old parent will be updated
+            invokeBeforeUpdateNode(newParentRef);                  // new parent ditto
         }
         
         // remove the child assoc from the old parent
@@ -430,14 +435,32 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
         // create a new assoc
         ChildAssoc newAssoc = nodeDaoService.newChildAssoc(newParentNode, nodeToMove, true, assocTypeQName, assocQName);
         
+        // If the node is moving stores, then drag the node hierarchy with it
+        if (movingStore)
+        {
+            // do the move
+            Store newStore = newParentNode.getStore();
+            moveNodeToStore(nodeToMove, newStore);
+            // the node reference will have changed too
+            nodeToMoveRef = nodeToMove.getNodeRef();
+        }
+        
         // check that no cyclic relationships have been created
         getPaths(nodeToMoveRef, false);
-        
+
         // invoke policy behaviour
-        invokeOnCreateChildAssociation(newAssoc.getChildAssocRef());
-        invokeOnDeleteChildAssociation(oldAssoc.getChildAssocRef());
-        invokeOnUpdateNode(oldParentNode.getNodeRef());
-        invokeOnUpdateNode(newParentRef);
+        if (movingStore)
+        {
+            invokeOnDeleteNode(oldAssocRef, nodeToMoveTypeQName, nodeToMoveAspects);
+            invokeOnCreateNode(newAssoc.getChildAssocRef());
+        }
+        else
+        {
+            invokeOnCreateChildAssociation(newAssoc.getChildAssocRef());
+            invokeOnDeleteChildAssociation(oldAssoc.getChildAssocRef());
+            invokeOnUpdateNode(oldParentNode.getNodeRef());
+            invokeOnUpdateNode(newParentRef);
+        }
         
         // update the node status
         nodeDaoService.recordChangeId(nodeToMoveRef);
@@ -1342,11 +1365,12 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
             nodeToMove.setStore(store);
             NodeRef newNodeRef = nodeToMove.getNodeRef();
             
-            // update change statuses
             String txnId = AlfrescoTransactionSupport.getTransactionId();
+            // update old status
             NodeStatus oldNodeStatus = nodeDaoService.getNodeStatus(oldNodeRef, true);
             oldNodeStatus.setNode(null);
             oldNodeStatus.setChangeTxnId(txnId);
+            // create the new status
             NodeStatus newNodeStatus = nodeDaoService.getNodeStatus(newNodeRef, true);
             newNodeStatus.setNode(nodeToMove);
             newNodeStatus.setChangeTxnId(txnId);
diff --git a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java
index 95d6d050fa..091e99c42d 100644
--- a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java
+++ b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java
@@ -181,6 +181,23 @@ public class PermissionServiceTest extends AbstractPermissionTest
         testSetNodePermissionEntry();
         testSetNodePermissionEntry2();
     }
+    
+    public void testDoubleSetAllowDeny()
+    {
+        Set permissionEntries = null;
+        // add-remove andy-all
+        permissionService.setPermission(rootNodeRef, "andy", permissionService.getAllPermission(), true);
+        permissionService.setPermission(rootNodeRef, "andy", permissionService.getAllPermission(), false);
+        permissionService.deletePermission(rootNodeRef, "andy", permissionService.getAllPermission());
+        permissionEntries = permissionService.getSetPermissions(rootNodeRef).getPermissionEntries();
+        assertEquals(0, permissionEntries.size());
+        // add-remove andy-read
+        permissionService.setPermission(rootNodeRef, "andy", PermissionService.READ, true);
+        permissionService.setPermission(rootNodeRef, "andy", PermissionService.READ, false);
+        permissionService.deletePermission(rootNodeRef, "andy", PermissionService.READ);
+        permissionEntries = permissionService.getSetPermissions(rootNodeRef).getPermissionEntries();
+        assertEquals(0, permissionEntries.size());
+    }
 
     public void testSetPermissionEntryElements()
     {
diff --git a/source/java/org/alfresco/repo/security/permissions/impl/hibernate/HibernatePermissionTest.java b/source/java/org/alfresco/repo/security/permissions/impl/hibernate/HibernatePermissionTest.java
index 4d84696c38..87933c23d7 100644
--- a/source/java/org/alfresco/repo/security/permissions/impl/hibernate/HibernatePermissionTest.java
+++ b/source/java/org/alfresco/repo/security/permissions/impl/hibernate/HibernatePermissionTest.java
@@ -119,13 +119,6 @@ public class HibernatePermissionTest extends BaseSpringTest
         // throw the reference away and get the a new one for the id
         permission = (DbPermission) getSession().load(DbPermissionImpl.class, id);
         assertNotNull("Permission not found", permission);
-        assertEquals("Test", permission.getName());
-        assertEquals(qname, permission.getTypeQname());
-        
-        // Test key
-        permission = (DbPermission) getSession().load(DbPermissionImpl.class, id);
-        assertNotNull("Permission not found", permission);
-        assertEquals("Test", permission.getName());
         assertEquals(qname, permission.getTypeQname());
     }
     
@@ -175,29 +168,29 @@ public class HibernatePermissionTest extends BaseSpringTest
         DbAccessControlList accessControlList = new DbAccessControlListImpl();
         accessControlList.setNode(node);
         accessControlList.setInherits(true);
+        Serializable nodeAclId = getSession().save(accessControlList);
         
         DbAuthority recipient = new DbAuthorityImpl();
         recipient.setRecipient("Test");
         recipient.getExternalKeys().add("One");
+        getSession().save(recipient);
         
         DbPermission permission = new DbPermissionImpl();
         permission.setTypeQname(qname);
         permission.setName("Test");
-        
-        DbAccessControlEntry accessControlEntry = DbAccessControlEntryImpl.create(accessControlList, permission, recipient, true);
-        
-        Serializable nodeAclId = getSession().save(accessControlList);
-        getSession().save(recipient);
         getSession().save(permission);
-        Serializable aceEntryId = getSession().save(accessControlEntry);
         
-        accessControlEntry =  (DbAccessControlEntry) getSession().load(DbAccessControlEntryImpl.class, aceEntryId);
+        DbAccessControlEntry accessControlEntry = accessControlList.newEntry(permission, recipient, true);
+        Long aceEntryId = accessControlEntry.getId();
+        assertNotNull("Entry is still transient", aceEntryId);
+        
+        accessControlEntry = (DbAccessControlEntry) getSession().load(DbAccessControlEntryImpl.class, aceEntryId);
         assertNotNull("Permission entry not found", accessControlEntry);
         assertTrue(accessControlEntry.isAllowed());
         assertNotNull(accessControlEntry.getAccessControlList());
         assertTrue(accessControlEntry.getAccessControlList().getInherits());
         assertNotNull(accessControlEntry.getPermission());
-        assertEquals("Test", accessControlEntry.getPermission().getName());
+        assertEquals("Test", accessControlEntry.getPermission().getKey().getName());
         assertNotNull(accessControlEntry.getAuthority());
         assertEquals("Test", accessControlEntry.getAuthority().getRecipient());
         assertEquals(1, accessControlEntry.getAuthority().getExternalKeys().size());
diff --git a/source/java/org/alfresco/repo/service/StoreRedirectorProxyFactory.java b/source/java/org/alfresco/repo/service/StoreRedirectorProxyFactory.java
index fe3fa2955f..d6fdfee7d2 100644
--- a/source/java/org/alfresco/repo/service/StoreRedirectorProxyFactory.java
+++ b/source/java/org/alfresco/repo/service/StoreRedirectorProxyFactory.java
@@ -253,11 +253,14 @@ public class StoreRedirectorProxyFactory implements FactoryBean, Initializing
                 // Only allow one store type
                 if (argStoreRef != null)
                 {
-                    if (storeRef != null && !storeRef.equals(argStoreRef))
-                    {
-                        throw new ServiceException("Multiple store types are not supported - types " + storeRef + " and " + argStoreRef + " passed");
-                    }
-                    storeRef = argStoreRef;
+                    // TODO: put some thought into the ramifications of allowing cross-store moves
+                    // TODO: The test here would only have checked storerefs adjacent to each other
+//                    if (storeRef != null && !storeRef.equals(argStoreRef))
+//                    {
+//                        throw new ServiceException("Multiple store types are not supported - types " + storeRef + " and " + argStoreRef + " passed");
+//                    }
+//                    storeRef = argStoreRef;
+                    return argStoreRef;
                 }
             }
 
diff --git a/source/java/org/alfresco/service/cmr/action/ActionDefinition.java b/source/java/org/alfresco/service/cmr/action/ActionDefinition.java
index 0c19c2b975..e5df61b3cf 100644
--- a/source/java/org/alfresco/service/cmr/action/ActionDefinition.java
+++ b/source/java/org/alfresco/service/cmr/action/ActionDefinition.java
@@ -16,6 +16,10 @@
  */
 package org.alfresco.service.cmr.action;
 
+import java.util.List;
+
+import org.alfresco.service.namespace.QName;
+
 
 
 /**
@@ -25,5 +29,10 @@ package org.alfresco.service.cmr.action;
  */
 public interface ActionDefinition extends ParameterizedItemDefinition
 {
-	
+    /**
+     * Gets a list of the types that this action item is applicable for
+     * 
+     * @return  list of types
+     */
+    public List getApplicableTypes();
 }
diff --git a/source/java/org/alfresco/service/cmr/action/ActionService.java b/source/java/org/alfresco/service/cmr/action/ActionService.java
index 7d2605c677..10ef0b641b 100644
--- a/source/java/org/alfresco/service/cmr/action/ActionService.java
+++ b/source/java/org/alfresco/service/cmr/action/ActionService.java
@@ -43,6 +43,15 @@ public interface ActionService
 	 * @return	the list action definitions
 	 */
 	List getActionDefinitions();
+    
+    /**
+     * Get all the action definitions that are applicable for the given node, based on
+     * its type and aspects.
+     * 
+     * @param nodeRef   the node reference
+     * @return          a list of applicable action definitions
+     */
+    List getActionDefinitions(NodeRef nodeRef);
 	
 	/**
 	 * Get a named action condition definition