mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-09 17:45:10 +00:00
Moved key column from access_control_list onto node
This eliminates several select statements issued while walking up the parent hierarchy The V1.2.1 - V1.3 script has been updated and tested, but if you want to keep an existing 1.3, then: SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE node ADD `acl_id` bigint(20) default NULL; UPDATE node node SET node.acl_id = (SELECT acl.id FROM access_control_list acl WHERE acl.node_id = node.id); SET FOREIGN_KEY_CHECKS = 1; git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2910 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
parent
272aad23f6
commit
516fc15cf4
@ -30,10 +30,6 @@ public interface DbAccessControlList
|
||||
{
|
||||
public long getId();
|
||||
|
||||
public Node getNode();
|
||||
|
||||
public void setNode(Node node);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Returns the access control entries for this access control list
|
||||
|
@ -26,8 +26,6 @@ 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.Session;
|
||||
@ -42,7 +40,6 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces
|
||||
private static Log logger = LogFactory.getLog(DbAccessControlListImpl.class);
|
||||
|
||||
private long id;
|
||||
private Node node;
|
||||
private Set<DbAccessControlEntry> entries;
|
||||
private boolean inherits;
|
||||
|
||||
@ -57,7 +54,6 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("DbAccessControlListImpl")
|
||||
.append("[ id=").append(id)
|
||||
.append(", node=").append(node)
|
||||
.append(", entries=").append(entries.size())
|
||||
.append(", inherits=").append(inherits)
|
||||
.append("]");
|
||||
@ -77,14 +73,13 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces
|
||||
}
|
||||
DbAccessControlList other = (DbAccessControlList) o;
|
||||
|
||||
return (this.inherits == other.getInherits())
|
||||
&& (EqualsHelper.nullSafeEquals(this.node, other.getNode()));
|
||||
return (this.inherits == other.getInherits());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return (node == null ? 0 : node.hashCode());
|
||||
return (inherits == false ? 0 : 17);
|
||||
}
|
||||
|
||||
public long getId()
|
||||
@ -101,16 +96,6 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Node getNode()
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
public void setNode(Node node)
|
||||
{
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public Set<DbAccessControlEntry> getEntries()
|
||||
{
|
||||
return entries;
|
||||
|
@ -28,6 +28,7 @@ import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.domain.ChildAssoc;
|
||||
import org.alfresco.repo.domain.DbAccessControlList;
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.repo.domain.NodeAssoc;
|
||||
import org.alfresco.repo.domain.NodeKey;
|
||||
@ -35,12 +36,14 @@ import org.alfresco.repo.domain.NodeStatus;
|
||||
import org.alfresco.repo.domain.PropertyValue;
|
||||
import org.alfresco.repo.domain.Store;
|
||||
import org.alfresco.repo.domain.StoreKey;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
|
||||
/**
|
||||
@ -385,6 +388,133 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
{
|
||||
txn.rollback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create some simple parent-child relationships and flush them. Then read them back in without
|
||||
* using the L2 cache.
|
||||
*/
|
||||
public void testQueryJoins() throws Exception
|
||||
{
|
||||
getSession().setCacheMode(CacheMode.IGNORE);
|
||||
|
||||
// make a container node
|
||||
Node containerNode = new NodeImpl();
|
||||
containerNode.setStore(store);
|
||||
containerNode.setUuid(GUID.generate());
|
||||
containerNode.setTypeQName(ContentModel.TYPE_CONTAINER);
|
||||
containerNode.getProperties().put(ContentModel.PROP_AUTHOR, new PropertyValue(DataTypeDefinition.TEXT, "ABC"));
|
||||
containerNode.getProperties().put(ContentModel.PROP_ARCHIVED_BY, new PropertyValue(DataTypeDefinition.TEXT, "ABC"));
|
||||
containerNode.getAspects().add(ContentModel.ASPECT_AUDITABLE);
|
||||
Serializable containerNodeId = getSession().save(containerNode);
|
||||
NodeKey containerNodeKey = new NodeKey(containerNode.getNodeRef());
|
||||
NodeStatus containerNodeStatus = new NodeStatusImpl();
|
||||
containerNodeStatus.setKey(containerNodeKey);
|
||||
containerNodeStatus.setNode(containerNode);
|
||||
containerNodeStatus.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId());
|
||||
getSession().save(containerNodeStatus);
|
||||
// make content node 1
|
||||
Node contentNode1 = new NodeImpl();
|
||||
contentNode1.setStore(store);
|
||||
contentNode1.setUuid(GUID.generate());
|
||||
contentNode1.setTypeQName(ContentModel.TYPE_CONTENT);
|
||||
contentNode1.getProperties().put(ContentModel.PROP_AUTHOR, new PropertyValue(DataTypeDefinition.TEXT, "ABC"));
|
||||
contentNode1.getProperties().put(ContentModel.PROP_ARCHIVED_BY, new PropertyValue(DataTypeDefinition.TEXT, "ABC"));
|
||||
contentNode1.getAspects().add(ContentModel.ASPECT_AUDITABLE);
|
||||
Serializable contentNode1Id = getSession().save(contentNode1);
|
||||
NodeKey contentNodeKey1 = new NodeKey(contentNode1.getNodeRef());
|
||||
NodeStatus contentNodeStatus1 = new NodeStatusImpl();
|
||||
contentNodeStatus1.setKey(contentNodeKey1);
|
||||
contentNodeStatus1.setNode(contentNode1);
|
||||
contentNodeStatus1.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId());
|
||||
getSession().save(contentNodeStatus1);
|
||||
// make content node 2
|
||||
Node contentNode2 = new NodeImpl();
|
||||
contentNode2.setStore(store);
|
||||
contentNode2.setUuid(GUID.generate());
|
||||
contentNode2.setTypeQName(ContentModel.TYPE_CONTENT);
|
||||
Serializable contentNode2Id = getSession().save(contentNode2);
|
||||
contentNode2.getProperties().put(ContentModel.PROP_AUTHOR, new PropertyValue(DataTypeDefinition.TEXT, "ABC"));
|
||||
contentNode2.getProperties().put(ContentModel.PROP_ARCHIVED_BY, new PropertyValue(DataTypeDefinition.TEXT, "ABC"));
|
||||
contentNode2.getAspects().add(ContentModel.ASPECT_AUDITABLE);
|
||||
NodeKey contentNodeKey2 = new NodeKey(contentNode2.getNodeRef());
|
||||
NodeStatus contentNodeStatus2 = new NodeStatusImpl();
|
||||
contentNodeStatus2.setKey(contentNodeKey2);
|
||||
contentNodeStatus2.setNode(contentNode2);
|
||||
contentNodeStatus2.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId());
|
||||
getSession().save(contentNodeStatus2);
|
||||
// create an association to content 1
|
||||
ChildAssoc assoc1 = new ChildAssocImpl();
|
||||
assoc1.setIsPrimary(true);
|
||||
assoc1.setTypeQName(QName.createQName(null, "type1"));
|
||||
assoc1.setQname(QName.createQName(null, "number1"));
|
||||
assoc1.buildAssociation(containerNode, contentNode1);
|
||||
getSession().save(assoc1);
|
||||
// create an association to content 2
|
||||
ChildAssoc assoc2 = new ChildAssocImpl();
|
||||
assoc2.setIsPrimary(true);
|
||||
assoc2.setTypeQName(QName.createQName(null, "type2"));
|
||||
assoc2.setQname(QName.createQName(null, "number2"));
|
||||
assoc2.buildAssociation(containerNode, contentNode2);
|
||||
getSession().save(assoc2);
|
||||
|
||||
// make sure that there are no entities cached in either L1 or L2
|
||||
getSession().flush();
|
||||
getSession().clear();
|
||||
|
||||
// now read the structure back in from the container down
|
||||
containerNodeStatus = (NodeStatus) getSession().get(NodeStatusImpl.class, containerNodeKey);
|
||||
containerNode = containerNodeStatus.getNode();
|
||||
Collection<ChildAssoc> assocs = containerNode.getChildAssocs();
|
||||
for (ChildAssoc assoc : assocs)
|
||||
{
|
||||
Node childNode = assoc.getChild();
|
||||
Store store = childNode.getStore();
|
||||
childNode.getAspects().size();
|
||||
childNode.getProperties().size();
|
||||
childNode.getParentAssocs().size();
|
||||
childNode.getChildAssocs().size();
|
||||
childNode.getSourceNodeAssocs().size();
|
||||
childNode.getTargetNodeAssocs().size();
|
||||
DbAccessControlList acl = childNode.getAccessControlList();
|
||||
if (acl != null)
|
||||
{
|
||||
acl.getEntries().size();
|
||||
}
|
||||
}
|
||||
|
||||
// clear out again
|
||||
getSession().clear();
|
||||
|
||||
// now remove a property from each child
|
||||
containerNodeStatus = (NodeStatus) getSession().get(NodeStatusImpl.class, containerNodeKey);
|
||||
containerNode = containerNodeStatus.getNode();
|
||||
assocs = containerNode.getChildAssocs();
|
||||
for (ChildAssoc assoc : assocs)
|
||||
{
|
||||
Node childNode = assoc.getChild();
|
||||
PropertyValue removed = childNode.getProperties().remove(ContentModel.PROP_ARCHIVED_BY);
|
||||
assertNotNull("Property was not present", removed);
|
||||
}
|
||||
// expect that just the specific property gets removed in the delete statement
|
||||
getSession().flush();
|
||||
getSession().clear();
|
||||
|
||||
// Create a second association to content 2
|
||||
// create an association to content 2
|
||||
containerNodeStatus = (NodeStatus) getSession().get(NodeStatusImpl.class, containerNodeKey);
|
||||
containerNode = containerNodeStatus.getNode();
|
||||
contentNodeStatus2 = (NodeStatus) getSession().get(NodeStatusImpl.class, contentNodeKey2);
|
||||
contentNode2 = contentNodeStatus2.getNode();
|
||||
ChildAssoc assoc3 = new ChildAssocImpl();
|
||||
assoc3.setIsPrimary(false);
|
||||
assoc3.setTypeQName(QName.createQName(null, "type3"));
|
||||
assoc3.setQname(QName.createQName(null, "number3"));
|
||||
assoc3.buildAssociation(containerNode, contentNode2); // check whether the children are pulled in for this
|
||||
getSession().save(assoc3);
|
||||
|
||||
// flush it
|
||||
getSession().flush();
|
||||
getSession().clear();
|
||||
}
|
||||
}
|
@ -38,14 +38,16 @@
|
||||
<property name="uuid" column="uuid" type="string" length="36" />
|
||||
</natural-id>
|
||||
<property name="typeQName" column="type_qname" type="QName" length="255" not-null="true" />
|
||||
<!-- inverse assoc to access control list -->
|
||||
<one-to-one
|
||||
<!-- forward assoc to access control list (optional) -->
|
||||
<many-to-one
|
||||
name="accessControlList"
|
||||
class="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl"
|
||||
property-ref="node"
|
||||
column="acl_id"
|
||||
lazy="false"
|
||||
fetch="join"
|
||||
cascade="delete" />
|
||||
unique="false"
|
||||
not-null="false"
|
||||
cascade="delete" />
|
||||
<!-- forward assoc to properties -->
|
||||
<map
|
||||
name="properties"
|
||||
@ -87,8 +89,8 @@
|
||||
<set
|
||||
name="parentAssocs"
|
||||
inverse="true"
|
||||
lazy="true"
|
||||
fetch="select"
|
||||
lazy="false"
|
||||
fetch="join"
|
||||
cascade="none"
|
||||
optimistic-lock="true" >
|
||||
<key column="child_node_id" />
|
||||
@ -98,8 +100,8 @@
|
||||
<set
|
||||
name="childAssocs"
|
||||
inverse="true"
|
||||
lazy="true"
|
||||
fetch="select"
|
||||
lazy="false"
|
||||
fetch="join"
|
||||
cascade="none"
|
||||
optimistic-lock="true" >
|
||||
<key column="parent_node_id" />
|
||||
@ -173,8 +175,8 @@
|
||||
<many-to-one
|
||||
name="parent"
|
||||
class="org.alfresco.repo.domain.hibernate.NodeImpl"
|
||||
lazy="false"
|
||||
fetch="join"
|
||||
lazy="proxy"
|
||||
fetch="select"
|
||||
optimistic-lock="true"
|
||||
not-null="true" >
|
||||
<column name="parent_node_id" />
|
||||
@ -182,8 +184,8 @@
|
||||
<!-- forward assoc to child node -->
|
||||
<many-to-one
|
||||
name="child"
|
||||
lazy="false"
|
||||
fetch="join"
|
||||
lazy="proxy"
|
||||
fetch="select"
|
||||
class="org.alfresco.repo.domain.hibernate.NodeImpl"
|
||||
optimistic-lock="true"
|
||||
not-null="true" >
|
||||
|
@ -19,14 +19,6 @@
|
||||
<generator class="native" />
|
||||
</id>
|
||||
|
||||
<many-to-one
|
||||
name="node"
|
||||
class="org.alfresco.repo.domain.hibernate.NodeImpl"
|
||||
unique="true"
|
||||
not-null="true">
|
||||
<column name="node_id" />
|
||||
</many-to-one>
|
||||
|
||||
<set name="entries"
|
||||
inverse="true"
|
||||
lazy="false"
|
||||
|
@ -39,7 +39,6 @@ import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.springframework.orm.hibernate3.HibernateCallback;
|
||||
@ -98,7 +97,7 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements
|
||||
}
|
||||
else
|
||||
{
|
||||
npe = createSimpleNodePermissionEntry(acl);
|
||||
npe = createSimpleNodePermissionEntry(node);
|
||||
}
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
@ -139,7 +138,6 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements
|
||||
private DbAccessControlList createAccessControlList(Node node)
|
||||
{
|
||||
DbAccessControlList acl = new DbAccessControlListImpl();
|
||||
acl.setNode(node);
|
||||
acl.setInherits(INHERIT_PERMISSIONS_DEFAULT);
|
||||
getHibernateTemplate().save(acl);
|
||||
|
||||
@ -184,10 +182,10 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements
|
||||
DbAccessControlList acl = getAccessControlList(node, false);
|
||||
if (acl != null)
|
||||
{
|
||||
// maintain referencial integrity
|
||||
node.setAccessControlList(null);
|
||||
// delete the access control list - it will cascade to the entries
|
||||
getHibernateTemplate().delete(acl);
|
||||
// maintain inverse
|
||||
node.setAccessControlList(null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -383,10 +381,10 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements
|
||||
DbAccessControlList acl = getAccessControlList(node, false);
|
||||
if (acl != null)
|
||||
{
|
||||
// maintain referencial integrity
|
||||
node.setAccessControlList(null);
|
||||
// drop the list
|
||||
getHibernateTemplate().delete(acl);
|
||||
// update node
|
||||
node.setAccessControlList(null);
|
||||
}
|
||||
// create the access control list
|
||||
acl = createAccessControlList(node);
|
||||
@ -452,25 +450,34 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements
|
||||
// Utility methods to create simple detached objects for the outside world
|
||||
// We do not pass out the hibernate objects
|
||||
|
||||
private SimpleNodePermissionEntry createSimpleNodePermissionEntry(DbAccessControlList acl)
|
||||
private SimpleNodePermissionEntry createSimpleNodePermissionEntry(Node node)
|
||||
{
|
||||
DbAccessControlList acl = node.getAccessControlList();
|
||||
if (acl == null)
|
||||
{
|
||||
ParameterCheck.mandatory("acl", acl);
|
||||
// there isn't an access control list for the node - spoof a null one
|
||||
SimpleNodePermissionEntry snpe = new SimpleNodePermissionEntry(
|
||||
node.getNodeRef(),
|
||||
true,
|
||||
Collections.<SimplePermissionEntry> emptySet());
|
||||
return snpe;
|
||||
}
|
||||
else
|
||||
{
|
||||
Set<DbAccessControlEntry> entries = acl.getEntries();
|
||||
SimpleNodePermissionEntry snpe = new SimpleNodePermissionEntry(
|
||||
node.getNodeRef(),
|
||||
acl.getInherits(),
|
||||
createSimplePermissionEntries(node, entries));
|
||||
return snpe;
|
||||
}
|
||||
Set<DbAccessControlEntry> entries = acl.getEntries();
|
||||
SimpleNodePermissionEntry snpe = new SimpleNodePermissionEntry(
|
||||
acl.getNode().getNodeRef(),
|
||||
acl.getInherits(),
|
||||
createSimplePermissionEntries(entries));
|
||||
return snpe;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entries access control entries
|
||||
* @return Returns a unique set of entries that can be given back to the outside world
|
||||
*/
|
||||
private Set<SimplePermissionEntry> createSimplePermissionEntries(Collection<DbAccessControlEntry> entries)
|
||||
private Set<SimplePermissionEntry> createSimplePermissionEntries(Node node, Collection<DbAccessControlEntry> entries)
|
||||
{
|
||||
if (entries == null)
|
||||
{
|
||||
@ -481,20 +488,20 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements
|
||||
{
|
||||
for (DbAccessControlEntry entry : entries)
|
||||
{
|
||||
spes.add(createSimplePermissionEntry(entry));
|
||||
spes.add(createSimplePermissionEntry(node, entry));
|
||||
}
|
||||
}
|
||||
return spes;
|
||||
}
|
||||
|
||||
private static SimplePermissionEntry createSimplePermissionEntry(DbAccessControlEntry ace)
|
||||
private static SimplePermissionEntry createSimplePermissionEntry(Node node, DbAccessControlEntry ace)
|
||||
{
|
||||
if (ace == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new SimplePermissionEntry(
|
||||
ace.getAccessControlList().getNode().getNodeRef(),
|
||||
node.getNodeRef(),
|
||||
createSimplePermissionReference(ace.getPermission()),
|
||||
ace.getAuthority().getRecipient(),
|
||||
ace.isAllowed() ? AccessStatus.ALLOWED : AccessStatus.DENIED);
|
||||
|
Loading…
x
Reference in New Issue
Block a user