mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Schema changes and ID-based node storage
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2727 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The interface against which permission entries are persisted
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
|
||||
public interface DbAccessControlEntry
|
||||
{
|
||||
/**
|
||||
* @return Returns the identifier for this object
|
||||
*/
|
||||
public long getId();
|
||||
|
||||
/**
|
||||
* @return Returns the containing access control list
|
||||
*/
|
||||
public DbAccessControlList getAccessControlList();
|
||||
|
||||
/**
|
||||
* @param acl the accession control list to which entry belongs
|
||||
*/
|
||||
public void setAccessControlList(DbAccessControlList acl);
|
||||
|
||||
/**
|
||||
* @return Returns the permission to which this entry applies
|
||||
*/
|
||||
public DbPermission getPermission();
|
||||
|
||||
/**
|
||||
* @param permission the permission to which the entry applies
|
||||
*/
|
||||
public void setPermission(DbPermission permission);
|
||||
|
||||
/**
|
||||
* @return Returns the authority to which this entry applies
|
||||
*/
|
||||
public DbAuthority getAuthority();
|
||||
|
||||
/**
|
||||
* @param authority the authority to which this entry applies
|
||||
*/
|
||||
public void setAuthority(DbAuthority authority);
|
||||
|
||||
/**
|
||||
* @return Returns <tt>true</tt> if this permission is allowed
|
||||
*/
|
||||
public boolean isAllowed();
|
||||
|
||||
/**
|
||||
* Set if this permission is allowed, otherwise it is denied.
|
||||
*
|
||||
* @param allowed
|
||||
*/
|
||||
public void setAllowed(boolean allowed);
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
/**
|
||||
* The interface to support persistence of node access control entries in hibernate
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public interface DbAccessControlList
|
||||
{
|
||||
public long getId();
|
||||
|
||||
public Node getNode();
|
||||
|
||||
public void setNode(Node node);
|
||||
|
||||
/**
|
||||
* Get inheritance behaviour
|
||||
* @return
|
||||
*/
|
||||
public boolean getInherits();
|
||||
|
||||
/**
|
||||
* Set inheritance behaviour
|
||||
* @param inherits
|
||||
*/
|
||||
public void setInherits(boolean inherits);
|
||||
|
||||
/**
|
||||
* Delete the entries related to this access control list
|
||||
*
|
||||
* @return Returns the number of entries deleted
|
||||
*/
|
||||
public int deleteEntries();
|
||||
}
|
49
source/java/org/alfresco/repo/domain/DbAuthority.java
Normal file
49
source/java/org/alfresco/repo/domain/DbAuthority.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 java.util.Set;
|
||||
|
||||
/**
|
||||
* The interface against which recipients of permission are persisted
|
||||
* @author andyh
|
||||
*/
|
||||
public interface DbAuthority extends Serializable
|
||||
{
|
||||
/**
|
||||
* @return Returns the recipient
|
||||
*/
|
||||
public String getRecipient();
|
||||
|
||||
/**
|
||||
* @param recipient the authority recipient
|
||||
*/
|
||||
public void setRecipient(String recipient);
|
||||
|
||||
/**
|
||||
* @return Returns the external keys associated with this authority
|
||||
*/
|
||||
public Set<String> getExternalKeys();
|
||||
|
||||
/**
|
||||
* Delete the access control entries related to this authority
|
||||
*
|
||||
* @return Returns the number of entries deleted
|
||||
*/
|
||||
public int deleteEntries();
|
||||
}
|
54
source/java/org/alfresco/repo/domain/DbPermission.java
Normal file
54
source/java/org/alfresco/repo/domain/DbPermission.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The interface against which permission references are persisted in hibernate.
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public interface DbPermission extends Serializable
|
||||
{
|
||||
/**
|
||||
* @return Returns the automatically assigned ID
|
||||
*/
|
||||
public long getId();
|
||||
|
||||
/**
|
||||
* @return Returns the qualified name of this permission
|
||||
*/
|
||||
public QName getTypeQname();
|
||||
|
||||
/**
|
||||
* @param qname the entity representing the qname for this instance
|
||||
*/
|
||||
public void setTypeQname(QName qname);
|
||||
|
||||
/**
|
||||
* @return Returns the permission name
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* @param name the name of the permission
|
||||
*/
|
||||
public void setName(String name);
|
||||
}
|
@@ -33,38 +33,33 @@ import org.alfresco.service.namespace.QName;
|
||||
public interface Node
|
||||
{
|
||||
/**
|
||||
* @return Returns the unique key for this node
|
||||
* Convenience method to get the reference to the node
|
||||
*
|
||||
* @return Returns the reference to this node
|
||||
*/
|
||||
public NodeKey getKey();
|
||||
|
||||
public NodeRef getNodeRef();
|
||||
|
||||
/**
|
||||
* @param key the unique node key
|
||||
* @return Returns the auto-generated ID
|
||||
*/
|
||||
public void setKey(NodeKey key);
|
||||
public Long getId();
|
||||
|
||||
public Store getStore();
|
||||
|
||||
public void setStore(Store store);
|
||||
|
||||
public String getUuid();
|
||||
|
||||
public void setUuid(String uuid);
|
||||
|
||||
public QName getTypeQName();
|
||||
|
||||
public void setTypeQName(QName typeQName);
|
||||
|
||||
/**
|
||||
* Set the status of the node. This is compulsory, but a node
|
||||
* status may exist without a node being present.
|
||||
*
|
||||
* @param nodeStatus
|
||||
*/
|
||||
public void setStatus(NodeStatus nodeStatus);
|
||||
|
||||
/**
|
||||
* Get the mandatory node status object
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public NodeStatus getStatus();
|
||||
|
||||
// public NodeStatus getStatus();
|
||||
//
|
||||
// public void setStatus(NodeStatus status);
|
||||
//
|
||||
public Set<QName> getAspects();
|
||||
|
||||
/**
|
||||
@@ -83,10 +78,7 @@ public interface Node
|
||||
|
||||
public Map<QName, PropertyValue> getProperties();
|
||||
|
||||
/**
|
||||
* Convenience method to get the reference to the node
|
||||
*
|
||||
* @return Returns the reference to this node
|
||||
*/
|
||||
public NodeRef getNodeRef();
|
||||
public DbAccessControlList getAccessControlList();
|
||||
|
||||
// public void setAccessControlList(DbAccessControlList accessControlList);
|
||||
}
|
||||
|
@@ -18,6 +18,8 @@ package org.alfresco.repo.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
|
||||
/**
|
||||
@@ -36,14 +38,26 @@ public class NodeKey implements Serializable
|
||||
public NodeKey()
|
||||
{
|
||||
}
|
||||
|
||||
public NodeKey(NodeRef nodeRef)
|
||||
{
|
||||
this(nodeRef.getStoreRef(), nodeRef.getId());
|
||||
}
|
||||
|
||||
public NodeKey(StoreKey storeKey, String guid)
|
||||
{
|
||||
setGuid(guid);
|
||||
setProtocol(storeKey.getProtocol());
|
||||
setIdentifier(storeKey.getIdentifier());
|
||||
}
|
||||
|
||||
public NodeKey(StoreRef storeRef, String guid)
|
||||
{
|
||||
setGuid(guid);
|
||||
setProtocol(storeRef.getProtocol());
|
||||
setIdentifier(storeRef.getIdentifier());
|
||||
}
|
||||
|
||||
public NodeKey(StoreKey storeKey, String guid)
|
||||
{
|
||||
setGuid(guid);
|
||||
setProtocol(storeKey.getProtocol());
|
||||
setIdentifier(storeKey.getIdentifier());
|
||||
}
|
||||
|
||||
public NodeKey(String protocol, String identifier, String guid)
|
||||
{
|
||||
setGuid(guid);
|
||||
|
@@ -37,11 +37,13 @@ public interface NodeStatus
|
||||
*/
|
||||
public void setKey(NodeKey key);
|
||||
|
||||
public Node getNode();
|
||||
|
||||
public void setNode(Node node);
|
||||
|
||||
public String getChangeTxnId();
|
||||
|
||||
public void setChangeTxnId(String txnId);
|
||||
|
||||
public void setDeleted(boolean deleted);
|
||||
|
||||
public boolean isDeleted();
|
||||
}
|
||||
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.dao;
|
||||
|
||||
import org.alfresco.repo.domain.QNameEntity;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Service layer accessing persistent <b>qname</b> entities directly
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public interface QNameDaoComponent
|
||||
{
|
||||
/**
|
||||
* Create a qname entity
|
||||
*
|
||||
* @param qname the qualified name to persist
|
||||
* @return Returns either a newly created instance or an existing matching instance
|
||||
*/
|
||||
public QNameEntity createQNameEntity(QName qname);
|
||||
|
||||
/**
|
||||
* @param qname the qname to match
|
||||
* @return Returns the entity if it exists, otherwise null
|
||||
*/
|
||||
public QNameEntity getQNameEntity(QName qname);
|
||||
|
||||
/**
|
||||
* @param namespaceUri the namespace URI
|
||||
* @param localName the localname part
|
||||
* @return Return the entity if it exists, otherwise null
|
||||
*/
|
||||
public QNameEntity getQNameEntity(String namespaceUri, String localName);
|
||||
}
|
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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.hibernate;
|
||||
|
||||
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.util.EqualsHelper;
|
||||
|
||||
/**
|
||||
* Persisted permission entries
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public class DbAccessControlEntryImpl implements DbAccessControlEntry
|
||||
{
|
||||
/** The object id */
|
||||
private long id;
|
||||
|
||||
/** The container of these entries */
|
||||
private DbAccessControlList accessControlList;
|
||||
|
||||
/** The permission to which this applies (non null - all is a special string) */
|
||||
private DbPermission permission;
|
||||
|
||||
/** The recipient to which this applies (non null - all is a special string) */
|
||||
private DbAuthority authority;
|
||||
|
||||
/** Is this permission allowed? */
|
||||
private boolean allowed;
|
||||
|
||||
public DbAccessControlEntryImpl()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("DbAccessControlEntryImpl")
|
||||
.append("[ id=").append(id)
|
||||
.append(", acl=").append(accessControlList.getId())
|
||||
.append(", permission=").append(permission.getId())
|
||||
.append(", authority=").append(authority.getRecipient())
|
||||
.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof 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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hashCode = accessControlList.hashCode();
|
||||
if (permission != null)
|
||||
{
|
||||
hashCode = hashCode * 37 + permission.hashCode();
|
||||
}
|
||||
if (authority != null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* For Hibernate use
|
||||
*/
|
||||
/* package */ void setId(long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public DbAccessControlList getAccessControlList()
|
||||
{
|
||||
return accessControlList;
|
||||
}
|
||||
|
||||
public void setAccessControlList(DbAccessControlList nodePermissionEntry)
|
||||
{
|
||||
this.accessControlList = nodePermissionEntry;
|
||||
}
|
||||
|
||||
public DbPermission getPermission()
|
||||
{
|
||||
return permission;
|
||||
}
|
||||
|
||||
public void setPermission(DbPermission permissionReference)
|
||||
{
|
||||
this.permission = permissionReference;
|
||||
}
|
||||
|
||||
public DbAuthority getAuthority()
|
||||
{
|
||||
return authority;
|
||||
}
|
||||
|
||||
public void setAuthority(DbAuthority recipient)
|
||||
{
|
||||
this.authority = recipient;
|
||||
}
|
||||
|
||||
public boolean isAllowed()
|
||||
{
|
||||
return allowed;
|
||||
}
|
||||
|
||||
public void setAllowed(boolean allowed)
|
||||
{
|
||||
this.allowed = allowed;
|
||||
}
|
||||
}
|
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.hibernate;
|
||||
|
||||
import org.alfresco.repo.domain.DbAccessControlList;
|
||||
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;
|
||||
|
||||
/**
|
||||
* The hibernate persisted class for node permission entries.
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public class DbAccessControlListImpl extends LifecycleAdapter implements DbAccessControlList
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(DbAccessControlListImpl.class);
|
||||
|
||||
private long id;
|
||||
private Node node;
|
||||
private boolean inherits;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("DbAccessControlListImpl")
|
||||
.append("[ id=").append(id)
|
||||
.append(", node=").append(node)
|
||||
.append(", inherits=").append(inherits)
|
||||
.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof DbAccessControlList))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DbAccessControlList other = (DbAccessControlList) o;
|
||||
|
||||
return (this.inherits == other.getInherits())
|
||||
&& (EqualsHelper.nullSafeEquals(this.node, other.getNode()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hibernate use
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Node getNode()
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
public void setNode(Node node)
|
||||
{
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public DbAccessControlListImpl()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public boolean getInherits()
|
||||
{
|
||||
return inherits;
|
||||
}
|
||||
|
||||
public void setInherits(boolean inherits)
|
||||
{
|
||||
this.inherits = inherits;
|
||||
}
|
||||
}
|
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.hibernate;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.domain.DbAuthority;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.CallbackException;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
|
||||
/**
|
||||
* The persisted class for authorities.
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public class DbAuthorityImpl extends LifecycleAdapter implements DbAuthority
|
||||
{
|
||||
private static final long serialVersionUID = -5582068692208928127L;
|
||||
|
||||
private static Log logger = LogFactory.getLog(DbAuthorityImpl.class);
|
||||
|
||||
private String recipient;
|
||||
private Set<String> externalKeys = new HashSet<String>();
|
||||
|
||||
public DbAuthorityImpl()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if(this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(!(o instanceof DbAuthority))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DbAuthority other = (DbAuthority)o;
|
||||
return this.getRecipient().equals(other.getRecipient());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return getRecipient().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_AUTHORITY)
|
||||
.setString("recipient", this.recipient);
|
||||
int count = HibernateHelper.deleteQueryResults(getSession(), query);
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Deleted " + count + " access entries for access control list " + this.recipient);
|
||||
}
|
||||
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 String getRecipient()
|
||||
{
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public void setRecipient(String recipient)
|
||||
{
|
||||
this.recipient = recipient;
|
||||
}
|
||||
|
||||
public Set<String> getExternalKeys()
|
||||
{
|
||||
return externalKeys;
|
||||
}
|
||||
|
||||
// Hibernate
|
||||
/* package */ void setExternalKeys(Set<String> externalKeys)
|
||||
{
|
||||
this.externalKeys = externalKeys;
|
||||
}
|
||||
}
|
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.hibernate;
|
||||
|
||||
import org.alfresco.repo.domain.DbPermission;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
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;
|
||||
|
||||
/**
|
||||
* The persisted class for permissions.
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public class DbPermissionImpl extends LifecycleAdapter implements DbPermission
|
||||
{
|
||||
private static final long serialVersionUID = -6352566900815035461L;
|
||||
|
||||
private static Log logger = LogFactory.getLog(DbPermissionImpl.class);
|
||||
|
||||
private long id;
|
||||
private QName typeQname;
|
||||
private String name;
|
||||
|
||||
public DbPermissionImpl()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("PermissionImpl")
|
||||
.append("[ id=").append(id)
|
||||
.append(", typeQname=").append(typeQname)
|
||||
.append(", name=").append(getName())
|
||||
.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if(this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(!(o instanceof DbPermission))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DbPermission other = (DbPermission)o;
|
||||
return (EqualsHelper.nullSafeEquals(typeQname, other.getTypeQname()))
|
||||
&& (EqualsHelper.nullSafeEquals(name, other.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return typeQname.hashCode() + (37 * name.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_PERMISSION)
|
||||
.setSerializable("permissionId", this.id);
|
||||
int count = HibernateHelper.deleteQueryResults(getSession(), query);
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Deleted " + count + " access entries for permission " + 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* For Hibernate use
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public QName getTypeQname()
|
||||
{
|
||||
return typeQname;
|
||||
}
|
||||
|
||||
public void setTypeQname(QName typeQname)
|
||||
{
|
||||
this.typeQname = typeQname;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to find a permission based on its natural key
|
||||
*
|
||||
* @param session the Hibernate session to use
|
||||
* @param qname the type qualified name
|
||||
* @param name the name of the permission
|
||||
* @return Returns an existing instance or null if not found
|
||||
*/
|
||||
public static DbPermission find(Session session, QName qname, String name)
|
||||
{
|
||||
Query query = session
|
||||
.getNamedQuery(PermissionsDaoComponentImpl.QUERY_GET_PERMISSION)
|
||||
.setString("permissionTypeQName", qname.toString())
|
||||
.setString("permissionName", name);
|
||||
return (DbPermission) query.uniqueResult();
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.hibernate;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.ObjectDeletedException;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.Session;
|
||||
|
||||
/**
|
||||
* Helper methods related to Hibernate
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public static int deleteQueryResults(Session session, Query query)
|
||||
{
|
||||
ScrollableResults entities = query.setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY);
|
||||
int count = 0;
|
||||
while (entities.next())
|
||||
{
|
||||
Object[] entityResults = entities.get();
|
||||
for (Object object : entityResults)
|
||||
{
|
||||
try
|
||||
{
|
||||
session.delete(object);
|
||||
}
|
||||
catch (ObjectDeletedException e)
|
||||
{
|
||||
// ignore - it's what we wanted
|
||||
}
|
||||
if (++count % 50 == 0)
|
||||
{
|
||||
session.flush();
|
||||
session.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
@@ -41,6 +41,7 @@ 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.exception.ConstraintViolationException;
|
||||
|
||||
/**
|
||||
* Test persistence and retrieval of Hibernate-specific implementations of the
|
||||
@@ -48,6 +49,7 @@ import org.alfresco.util.GUID;
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class HibernateNodeTest extends BaseSpringTest
|
||||
{
|
||||
private static final String TEST_NAMESPACE = "http://www.alfresco.org/test/HibernateNodeTest";
|
||||
@@ -62,7 +64,7 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
{
|
||||
store = new StoreImpl();
|
||||
StoreKey storeKey = new StoreKey(StoreRef.PROTOCOL_WORKSPACE,
|
||||
"TestWorkspace@" + System.currentTimeMillis());
|
||||
"TestWorkspace@" + System.currentTimeMillis() + " - " + System.nanoTime());
|
||||
store.setKey(storeKey);
|
||||
// persist so that it is present in the hibernate cache
|
||||
getSession().save(store);
|
||||
@@ -82,46 +84,13 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
|
||||
public void testGetStore() throws Exception
|
||||
{
|
||||
NodeKey key = new NodeKey("Random Protocol", "Random Identifier", "AAA");
|
||||
// create the node status
|
||||
NodeStatus nodeStatus = new NodeStatusImpl();
|
||||
nodeStatus.setKey(key);
|
||||
nodeStatus.setDeleted(false);
|
||||
nodeStatus.setChangeTxnId("txn:123");
|
||||
getSession().save(nodeStatus);
|
||||
// create a new Node
|
||||
Node node = new NodeImpl();
|
||||
node.setKey(key);
|
||||
node.setStore(store); // not meaningful as it contradicts the key
|
||||
node.setTypeQName(ContentModel.TYPE_CONTAINER);
|
||||
node.setStatus(nodeStatus);
|
||||
// persist it
|
||||
try
|
||||
{
|
||||
Serializable id = getSession().save(node);
|
||||
fail("No store exists");
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
// this should not solve the problem
|
||||
node.setStore(store);
|
||||
// persist it
|
||||
try
|
||||
{
|
||||
Serializable id = getSession().save(node);
|
||||
fail("Setting store does not persist protocol and identifier attributes");
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
|
||||
// fix the key
|
||||
key = new NodeKey(store.getKey().getProtocol(), store.getKey().getIdentifier(), "AAA");
|
||||
node.setKey(key);
|
||||
// now it should work
|
||||
node.setUuid(GUID.generate());
|
||||
node.setTypeQName(ContentModel.TYPE_CONTAINER);
|
||||
|
||||
// now it should work
|
||||
Serializable id = getSession().save(node);
|
||||
|
||||
// throw the reference away and get the a new one for the id
|
||||
@@ -139,36 +108,42 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
// create the node status
|
||||
NodeStatus nodeStatus = new NodeStatusImpl();
|
||||
nodeStatus.setKey(key);
|
||||
nodeStatus.setDeleted(false);
|
||||
nodeStatus.setChangeTxnId("txn:123");
|
||||
getSession().save(nodeStatus);
|
||||
|
||||
// it must be able to exist without the node
|
||||
flushAndClear();
|
||||
|
||||
// create a new Node
|
||||
Node node = new NodeImpl();
|
||||
node.setStore(store);
|
||||
node.setKey(key);
|
||||
node.setStore(store); // not meaningful as it contradicts the key
|
||||
node.setUuid(GUID.generate());
|
||||
node.setTypeQName(ContentModel.TYPE_CONTAINER);
|
||||
node.setStatus(nodeStatus);
|
||||
Serializable id = getSession().save(node);
|
||||
|
||||
// flush
|
||||
Serializable nodeId = getSession().save(node);
|
||||
|
||||
// This should all be fine. The node does not HAVE to have a status.
|
||||
flushAndClear();
|
||||
|
||||
// is the status retrievable
|
||||
node = (Node) getSession().get(NodeImpl.class, id);
|
||||
nodeStatus = node.getStatus();
|
||||
|
||||
// set the node
|
||||
nodeStatus = (NodeStatus) getSession().get(NodeStatusImpl.class, key);
|
||||
nodeStatus.setNode(node);
|
||||
flushAndClear();
|
||||
|
||||
// is the node retrievable?
|
||||
nodeStatus = (NodeStatus) getSession().get(NodeStatusImpl.class, key);
|
||||
node = nodeStatus.getNode();
|
||||
assertNotNull("Node was not attached to status", node);
|
||||
// change the values
|
||||
nodeStatus.setChangeTxnId("txn:456");
|
||||
nodeStatus.setDeleted(true);
|
||||
// delete the node
|
||||
getSession().delete(node);
|
||||
|
||||
// flush
|
||||
flushAndClear();
|
||||
try
|
||||
{
|
||||
flushAndClear();
|
||||
fail("Node status may not refer to non-existent node");
|
||||
}
|
||||
catch(ConstraintViolationException e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,18 +151,11 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
*/
|
||||
public void testProperties() throws Exception
|
||||
{
|
||||
NodeKey key = new NodeKey(store.getKey(), "AAA");
|
||||
// create the node status
|
||||
NodeStatus nodeStatus = new NodeStatusImpl();
|
||||
nodeStatus.setKey(key);
|
||||
nodeStatus.setDeleted(false);
|
||||
nodeStatus.setChangeTxnId("txn:123");
|
||||
getSession().save(nodeStatus);
|
||||
// create a new Node
|
||||
Node node = new NodeImpl();
|
||||
node.setKey(key);
|
||||
node.setStore(store);
|
||||
node.setUuid(GUID.generate());
|
||||
node.setTypeQName(ContentModel.TYPE_CONTAINER);
|
||||
node.setStatus(nodeStatus);
|
||||
// give it a property map
|
||||
Map<QName, PropertyValue> propertyMap = new HashMap<QName, PropertyValue>(5);
|
||||
QName propertyQName = QName.createQName("{}A");
|
||||
@@ -213,19 +181,11 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
*/
|
||||
public void testAspects() throws Exception
|
||||
{
|
||||
NodeKey key = new NodeKey(store.getKey(), GUID.generate());
|
||||
// create the node status
|
||||
NodeStatus nodeStatus = new NodeStatusImpl();
|
||||
nodeStatus.setKey(key);
|
||||
nodeStatus.setDeleted(false);
|
||||
nodeStatus.setChangeTxnId("txn:123");
|
||||
getSession().save(nodeStatus);
|
||||
// make a real node
|
||||
Node node = new NodeImpl();
|
||||
node.setKey(key);
|
||||
node.setStore(store);
|
||||
node.setUuid(GUID.generate());
|
||||
node.setTypeQName(ContentModel.TYPE_CMOBJECT);
|
||||
node.setStatus(nodeStatus);
|
||||
|
||||
// add some aspects
|
||||
QName aspect1 = QName.createQName(TEST_NAMESPACE, "1");
|
||||
@@ -254,33 +214,20 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
|
||||
public void testNodeAssoc() throws Exception
|
||||
{
|
||||
NodeKey sourceKey = new NodeKey(store.getKey(), GUID.generate());
|
||||
// make a source node
|
||||
NodeStatus sourceNodeStatus = new NodeStatusImpl();
|
||||
sourceNodeStatus.setKey(sourceKey);
|
||||
sourceNodeStatus.setDeleted(false);
|
||||
sourceNodeStatus.setChangeTxnId("txn:123");
|
||||
getSession().save(sourceNodeStatus);
|
||||
Node sourceNode = new NodeImpl();
|
||||
sourceNode.setKey(sourceKey);
|
||||
sourceNode.setStore(store);
|
||||
sourceNode.setUuid(GUID.generate());
|
||||
sourceNode.setTypeQName(ContentModel.TYPE_CMOBJECT);
|
||||
sourceNode.setStatus(sourceNodeStatus);
|
||||
Serializable realNodeKey = getSession().save(sourceNode);
|
||||
Serializable realNodeId = getSession().save(sourceNode);
|
||||
|
||||
// make a container node
|
||||
NodeKey targetKey = new NodeKey(store.getKey(), GUID.generate());
|
||||
NodeStatus targetNodeStatus = new NodeStatusImpl();
|
||||
targetNodeStatus.setKey(targetKey);
|
||||
targetNodeStatus.setDeleted(false);
|
||||
targetNodeStatus.setChangeTxnId("txn:123");
|
||||
getSession().save(targetNodeStatus);
|
||||
Node targetNode = new NodeImpl();
|
||||
targetNode.setKey(targetKey);
|
||||
targetNode.setStore(store);
|
||||
targetNode.setStore(store);
|
||||
targetNode.setUuid(GUID.generate());
|
||||
targetNode.setTypeQName(ContentModel.TYPE_CONTAINER);
|
||||
targetNode.setStatus(targetNodeStatus);
|
||||
Serializable containerNodeKey = getSession().save(targetNode);
|
||||
Serializable containerNodeId = getSession().save(targetNode);
|
||||
|
||||
// create an association between them
|
||||
NodeAssoc assoc = new NodeAssocImpl();
|
||||
@@ -299,13 +246,13 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
getSession().clear();
|
||||
|
||||
// reload the source
|
||||
sourceNode = (Node) getSession().get(NodeImpl.class, sourceKey);
|
||||
sourceNode = (Node) getSession().get(NodeImpl.class, realNodeId);
|
||||
assertNotNull("Source node not found", sourceNode);
|
||||
// check that the associations are present
|
||||
assertEquals("Expected exactly 2 target assocs", 2, sourceNode.getTargetNodeAssocs().size());
|
||||
|
||||
// reload the target
|
||||
targetNode = (Node) getSession().get(NodeImpl.class, targetKey);
|
||||
targetNode = (Node) getSession().get(NodeImpl.class, containerNodeId);
|
||||
assertNotNull("Target node not found", targetNode);
|
||||
// check that the associations are present
|
||||
assertEquals("Expected exactly 2 source assocs", 2, targetNode.getSourceNodeAssocs().size());
|
||||
@@ -314,32 +261,17 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
public void testChildAssoc() throws Exception
|
||||
{
|
||||
// make a content node
|
||||
NodeKey key = new NodeKey(store.getKey(), GUID.generate());
|
||||
NodeStatus contentNodeStatus = new NodeStatusImpl();
|
||||
contentNodeStatus.setKey(key);
|
||||
contentNodeStatus.setDeleted(false);
|
||||
contentNodeStatus.setChangeTxnId("txn:123");
|
||||
getSession().save(contentNodeStatus);
|
||||
Node contentNode = new NodeImpl();
|
||||
contentNode.setKey(key);
|
||||
contentNode.setStore(store);
|
||||
contentNode.setTypeQName(ContentModel.TYPE_CONTENT);
|
||||
contentNode.setStatus(contentNodeStatus);
|
||||
Serializable contentNodeKey = getSession().save(contentNode);
|
||||
Serializable contentNodeId = getSession().save(contentNode);
|
||||
|
||||
// make a container node
|
||||
key = new NodeKey(store.getKey(), GUID.generate());
|
||||
NodeStatus containerNodeStatus = new NodeStatusImpl();
|
||||
containerNodeStatus.setKey(key);
|
||||
containerNodeStatus.setDeleted(false);
|
||||
containerNodeStatus.setChangeTxnId("txn:123");
|
||||
getSession().save(containerNodeStatus);
|
||||
Node containerNode = new NodeImpl();
|
||||
containerNode.setKey(key);
|
||||
containerNode.setStore(store);
|
||||
containerNode.setUuid(GUID.generate());
|
||||
containerNode.setTypeQName(ContentModel.TYPE_CONTAINER);
|
||||
containerNode.setStatus(containerNodeStatus);
|
||||
Serializable containerNodeKey = getSession().save(containerNode);
|
||||
Serializable containerNodeId = getSession().save(containerNode);
|
||||
// create an association to the content
|
||||
ChildAssoc assoc1 = new ChildAssocImpl();
|
||||
assoc1.setIsPrimary(true);
|
||||
@@ -362,7 +294,7 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
// flushAndClear();
|
||||
|
||||
// reload the container
|
||||
containerNode = (Node) getSession().get(NodeImpl.class, containerNodeKey);
|
||||
containerNode = (Node) getSession().get(NodeImpl.class, containerNodeId);
|
||||
assertNotNull("Node not found", containerNode);
|
||||
// check
|
||||
assertEquals("Expected exactly 2 children", 2, containerNode.getChildAssocs().size());
|
||||
@@ -371,8 +303,8 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
ChildAssoc assoc = (ChildAssoc) iterator.next();
|
||||
// the node id must be known
|
||||
assertNotNull("Node not populated on assoc", assoc.getChild());
|
||||
assertEquals("Node key on child assoc is incorrect", contentNodeKey,
|
||||
assoc.getChild().getKey());
|
||||
assertEquals("Node key on child assoc is incorrect",
|
||||
contentNodeId, assoc.getChild().getId());
|
||||
}
|
||||
|
||||
// check that we can traverse the association from the child
|
||||
@@ -397,20 +329,12 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
*/
|
||||
public void testCaching() throws Exception
|
||||
{
|
||||
NodeKey key = new NodeKey(store.getKey(), GUID.generate());
|
||||
|
||||
// make a node
|
||||
NodeStatus nodeStatus = new NodeStatusImpl();
|
||||
nodeStatus.setKey(key);
|
||||
nodeStatus.setDeleted(false);
|
||||
nodeStatus.setChangeTxnId("txn:123");
|
||||
getSession().save(nodeStatus);
|
||||
Node node = new NodeImpl();
|
||||
node.setKey(key);
|
||||
node.setStore(store);
|
||||
node.setUuid(GUID.generate());
|
||||
node.setTypeQName(ContentModel.TYPE_CONTENT);
|
||||
node.setStatus(nodeStatus);
|
||||
getSession().save(node);
|
||||
Serializable nodeId = getSession().save(node);
|
||||
|
||||
// add some aspects to the node
|
||||
Set<QName> aspects = node.getAspects();
|
||||
@@ -421,7 +345,7 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
properties.put(ContentModel.PROP_NAME, new PropertyValue(DataTypeDefinition.TEXT, "ABC"));
|
||||
|
||||
// check that the session hands back the same instance
|
||||
Node checkNode = (Node) getSession().get(NodeImpl.class, key);
|
||||
Node checkNode = (Node) getSession().get(NodeImpl.class, nodeId);
|
||||
assertNotNull(checkNode);
|
||||
assertTrue("Node retrieved was not same instance", checkNode == node);
|
||||
|
||||
@@ -448,7 +372,7 @@ public class HibernateNodeTest extends BaseSpringTest
|
||||
txn.begin();
|
||||
|
||||
// check that the L2 cache hands back the same instance
|
||||
checkNode = (Node) getSession().get(NodeImpl.class, key);
|
||||
checkNode = (Node) getSession().get(NodeImpl.class, nodeId);
|
||||
assertNotNull(checkNode);
|
||||
checkAspects = checkNode.getAspects();
|
||||
|
||||
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.hibernate;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.CallbackException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.classic.Lifecycle;
|
||||
|
||||
/**
|
||||
* Helper base class providing lifecycle and other support
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public abstract class LifecycleAdapter implements Lifecycle
|
||||
{
|
||||
/** Helper */
|
||||
private Session session;
|
||||
|
||||
/**
|
||||
* @return Returns the session that this object was used in
|
||||
*/
|
||||
protected Session getSession()
|
||||
{
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns NO_VETO always
|
||||
*/
|
||||
public boolean onDelete(Session session) throws CallbackException
|
||||
{
|
||||
return NO_VETO;
|
||||
}
|
||||
|
||||
/** NO OP */
|
||||
public void onLoad(Session session, Serializable id)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/** @return Returns NO_VETO always */
|
||||
public boolean onSave(Session session) throws CallbackException
|
||||
{
|
||||
this.session = session;
|
||||
return NO_VETO;
|
||||
}
|
||||
|
||||
/** @return Returns NO_VETO always */
|
||||
public boolean onUpdate(Session session) throws CallbackException
|
||||
{
|
||||
this.session = session;
|
||||
return NO_VETO;
|
||||
}
|
||||
}
|
@@ -17,21 +17,41 @@
|
||||
select-before-update="false"
|
||||
lazy="true"
|
||||
optimistic-lock="version" >
|
||||
<!-- composite PK -->
|
||||
<composite-id name="key" class="org.alfresco.repo.domain.NodeKey">
|
||||
<key-property name="protocol" length="50" />
|
||||
<key-property name="identifier" length="100" />
|
||||
<key-property name="guid" length="36"/>
|
||||
</composite-id>
|
||||
<!-- auto-generated ID -->
|
||||
<id name="id" column="id" type="long" >
|
||||
<generator class="native" />
|
||||
</id>
|
||||
<!-- forward assoc to store -->
|
||||
<many-to-one
|
||||
name="store"
|
||||
class="org.alfresco.repo.domain.hibernate.StoreImpl"
|
||||
not-null="true"
|
||||
lazy="no-proxy"
|
||||
optimistic-lock="true"
|
||||
fetch="select">
|
||||
<column name="protocol" not-null="true" />
|
||||
<column name="identifier" not-null="true" />
|
||||
</many-to-one>
|
||||
<!-- the store-unique identifier -->
|
||||
<property name="uuid" column="uuid" type="string" length="36" />
|
||||
<property name="typeQName" column="type_qname" type="QName" length="255" not-null="true" />
|
||||
<!-- forward assoc to node status -->
|
||||
<!-- inverse assoc to access control list -->
|
||||
<one-to-one
|
||||
name="accessControlList"
|
||||
class="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl"
|
||||
property-ref="node"
|
||||
lazy="no-proxy"
|
||||
fetch="select"
|
||||
cascade="delete" />
|
||||
<!-- inverse assoc to node status -->
|
||||
<!--
|
||||
<one-to-one
|
||||
name="status"
|
||||
class="org.alfresco.repo.domain.hibernate.NodeStatusImpl"
|
||||
constrained="true"
|
||||
property-ref="node"
|
||||
lazy="no-proxy"
|
||||
fetch="select">
|
||||
</one-to-one>
|
||||
fetch="select" />
|
||||
-->
|
||||
<!-- forward assoc to properties -->
|
||||
<map
|
||||
name="properties"
|
||||
@@ -42,12 +62,8 @@
|
||||
inverse="false"
|
||||
optimistic-lock="true"
|
||||
cascade="delete" >
|
||||
<key>
|
||||
<column name="protocol" length="50" />
|
||||
<column name="identifier" length="100" />
|
||||
<column name="guid" length="36" />
|
||||
</key>
|
||||
<map-key column="qname" type="QName" length="128" />
|
||||
<key column="node_id" not-null="true" />
|
||||
<map-key column="qname" type="QName" length="200" />
|
||||
<composite-element class="org.alfresco.repo.domain.PropertyValue" >
|
||||
<property name="actualType" column="actual_type" type="string" length="15" not-null="true" />
|
||||
<property name="multiValued" column="multi_valued" type="boolean" not-null="true" />
|
||||
@@ -70,26 +86,9 @@
|
||||
fetch="select"
|
||||
optimistic-lock="true"
|
||||
cascade="delete" >
|
||||
<key>
|
||||
<column name="protocol" length="50" />
|
||||
<column name="identifier" length="100" />
|
||||
<column name="guid" length="36" />
|
||||
</key>
|
||||
<element column="qname" type="QName" length="128"/>
|
||||
<key column="node_id" not-null="true" />
|
||||
<element column="qname" type="QName" length="200"/>
|
||||
</set>
|
||||
<!-- forward assoc to store -->
|
||||
<many-to-one
|
||||
name="store"
|
||||
class="org.alfresco.repo.domain.hibernate.StoreImpl"
|
||||
not-null="true"
|
||||
insert="false"
|
||||
update="false"
|
||||
lazy="no-proxy"
|
||||
optimistic-lock="true"
|
||||
fetch="select">
|
||||
<column name="protocol" />
|
||||
<column name="identifier" />
|
||||
</many-to-one>
|
||||
<!-- inverse assoc to parent childassocs -->
|
||||
<bag
|
||||
name="parentAssocs"
|
||||
@@ -98,11 +97,7 @@
|
||||
cascade="none"
|
||||
optimistic-lock="true"
|
||||
fetch="select" >
|
||||
<key>
|
||||
<column name="child_protocol" />
|
||||
<column name="child_identifier" />
|
||||
<column name="child_guid" length="36" />
|
||||
</key>
|
||||
<key column="child_node_id" />
|
||||
<one-to-many class="org.alfresco.repo.domain.hibernate.ChildAssocImpl" />
|
||||
</bag>
|
||||
<!-- inverse assoc to child childassocs -->
|
||||
@@ -113,13 +108,8 @@
|
||||
cascade="none"
|
||||
optimistic-lock="true"
|
||||
fetch="select" >
|
||||
<key>
|
||||
<column name="parent_protocol" />
|
||||
<column name="parent_identifier" />
|
||||
<column name="parent_guid" length="36" />
|
||||
</key>
|
||||
<key column="parent_node_id" />
|
||||
<one-to-many class="org.alfresco.repo.domain.hibernate.ChildAssocImpl" />
|
||||
|
||||
</bag>
|
||||
<!-- inverse assoc to source nodeassocs -->
|
||||
<bag
|
||||
@@ -127,11 +117,7 @@
|
||||
inverse="true"
|
||||
cascade="none"
|
||||
optimistic-lock="true" >
|
||||
<key>
|
||||
<column name="target_protocol" />
|
||||
<column name="target_identifier" />
|
||||
<column name="target_guid" length="36" />
|
||||
</key>
|
||||
<key column="target_node_id" />
|
||||
<one-to-many class="org.alfresco.repo.domain.hibernate.NodeAssocImpl" />
|
||||
</bag>
|
||||
<!-- inverse assoc to target nodeassocs -->
|
||||
@@ -140,11 +126,7 @@
|
||||
inverse="true"
|
||||
cascade="none"
|
||||
optimistic-lock="true" >
|
||||
<key>
|
||||
<column name="source_protocol" />
|
||||
<column name="source_identifier" />
|
||||
<column name="source_guid" length="36" />
|
||||
</key>
|
||||
<key column="source_node_id" />
|
||||
<one-to-many class="org.alfresco.repo.domain.hibernate.NodeAssocImpl" />
|
||||
</bag>
|
||||
</class>
|
||||
@@ -162,8 +144,17 @@
|
||||
<composite-id name="key" class="org.alfresco.repo.domain.NodeKey">
|
||||
<key-property name="protocol" length="50" />
|
||||
<key-property name="identifier" length="100" />
|
||||
<key-property name="guid" length="36"/>
|
||||
<key-property name="guid" length="36" />
|
||||
</composite-id>
|
||||
<!-- forward assoc to node (optional) -->
|
||||
<many-to-one
|
||||
name="node"
|
||||
class="org.alfresco.repo.domain.hibernate.NodeImpl"
|
||||
column="node_id"
|
||||
unique="true"
|
||||
not-null="false"
|
||||
fetch="join"
|
||||
lazy="false" />
|
||||
<property name="changeTxnId" column="change_txn_id" type="string" length="56" not-null="true" />
|
||||
<property name="deleted" column="deleted" type="boolean" not-null="true" />
|
||||
</class>
|
||||
@@ -176,15 +167,13 @@
|
||||
lazy="true"
|
||||
optimistic-lock="version"
|
||||
table="child_assoc" >
|
||||
<id
|
||||
name="id"
|
||||
column="id"
|
||||
type="long" >
|
||||
<generator class="increment" />
|
||||
<!-- auto-generated ID -->
|
||||
<id name="id" column="id" type="long" >
|
||||
<generator class="native" />
|
||||
</id>
|
||||
<property name="typeQName" column="type_qname" type="QName" length="255" not-null="true" />
|
||||
<property name="qname" column="qname" type="QName" length="255" not-null="true" />
|
||||
<property name="isPrimary" />
|
||||
<property name="isPrimary" column="is_primary" />
|
||||
<property name="index" column="assoc_index" />
|
||||
<!-- forward assoc to parent node -->
|
||||
<many-to-one
|
||||
@@ -194,9 +183,7 @@
|
||||
fetch="join"
|
||||
optimistic-lock="true"
|
||||
not-null="true" >
|
||||
<column name="parent_protocol" />
|
||||
<column name="parent_identifier" />
|
||||
<column name="parent_guid" length="36" />
|
||||
<column name="parent_node_id" />
|
||||
</many-to-one>
|
||||
<!-- forward assoc to child node -->
|
||||
<many-to-one
|
||||
@@ -206,9 +193,7 @@
|
||||
class="org.alfresco.repo.domain.hibernate.NodeImpl"
|
||||
optimistic-lock="true"
|
||||
not-null="true" >
|
||||
<column name="child_protocol" />
|
||||
<column name="child_identifier" />
|
||||
<column name="child_guid" length="36" />
|
||||
<column name="child_node_id" />
|
||||
</many-to-one>
|
||||
</class>
|
||||
|
||||
@@ -216,11 +201,9 @@
|
||||
name="org.alfresco.repo.domain.hibernate.NodeAssocImpl"
|
||||
proxy="org.alfresco.repo.domain.NodeAssoc"
|
||||
table="node_assoc" >
|
||||
<id
|
||||
name="id"
|
||||
column="id"
|
||||
type="long" >
|
||||
<generator class="increment" />
|
||||
<!-- auto-generated ID -->
|
||||
<id name="id" column="id" type="long" >
|
||||
<generator class="native" />
|
||||
</id>
|
||||
<property name="typeQName" column="type_qname" type="QName" length="255" not-null="true" />
|
||||
<!-- forward assoc to source node -->
|
||||
@@ -228,18 +211,14 @@
|
||||
name="source"
|
||||
class="org.alfresco.repo.domain.hibernate.NodeImpl"
|
||||
not-null="true" >
|
||||
<column name="source_protocol" />
|
||||
<column name="source_identifier" />
|
||||
<column name="source_guid" length="36" />
|
||||
<column name="source_node_id" />
|
||||
</many-to-one>
|
||||
<!-- forward assoc to target node -->
|
||||
<many-to-one
|
||||
name="target"
|
||||
class="org.alfresco.repo.domain.hibernate.NodeImpl"
|
||||
not-null="true" >
|
||||
<column name="target_protocol" />
|
||||
<column name="target_identifier" />
|
||||
<column name="target_guid" length="36" />
|
||||
<column name="target_node_id" />
|
||||
</many-to-one>
|
||||
</class>
|
||||
|
||||
@@ -254,30 +233,21 @@
|
||||
select
|
||||
assoc
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.NodeImpl as source
|
||||
join source.targetNodeAssocs as assoc
|
||||
join assoc.target as target
|
||||
org.alfresco.repo.domain.hibernate.NodeAssocImpl as assoc
|
||||
where
|
||||
source.key.protocol = :sourceKeyProtocol and
|
||||
source.key.identifier = :sourceKeyIdentifier and
|
||||
source.key.guid = :sourceKeyGuid and
|
||||
assoc.typeQName = :assocTypeQName and
|
||||
target.key.protocol = :targetKeyProtocol and
|
||||
target.key.identifier = :targetKeyIdentifier and
|
||||
target.key.guid = :targetKeyGuid
|
||||
assoc.source = :sourceNode and
|
||||
assoc.target = :targetNode and
|
||||
assoc.typeQName = :assocTypeQName
|
||||
</query>
|
||||
|
||||
<query name="node.GetNodeAssocTargets">
|
||||
select
|
||||
target
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.NodeImpl as source
|
||||
join source.targetNodeAssocs as assoc
|
||||
org.alfresco.repo.domain.hibernate.NodeAssocImpl as assoc
|
||||
join assoc.target as target
|
||||
where
|
||||
source.key.protocol = :sourceKeyProtocol and
|
||||
source.key.identifier = :sourceKeyIdentifier and
|
||||
source.key.guid = :sourceKeyGuid and
|
||||
assoc.source = :sourceNode and
|
||||
assoc.typeQName = :assocTypeQName
|
||||
</query>
|
||||
|
||||
@@ -285,13 +255,10 @@
|
||||
select
|
||||
source
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.NodeImpl as target
|
||||
join target.sourceNodeAssocs as assoc
|
||||
org.alfresco.repo.domain.hibernate.NodeAssocImpl as assoc
|
||||
join assoc.source as source
|
||||
where
|
||||
target.key.protocol = :targetKeyProtocol and
|
||||
target.key.identifier = :targetKeyIdentifier and
|
||||
target.key.guid = :targetKeyGuid and
|
||||
assoc.target = :targetNode and
|
||||
assoc.typeQName = :assocTypeQName
|
||||
</query>
|
||||
|
||||
|
@@ -112,6 +112,7 @@ public class NodeAssocImpl implements NodeAssoc
|
||||
/**
|
||||
* For Hibernate use
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(long id)
|
||||
{
|
||||
this.id = id;
|
||||
|
@@ -22,11 +22,14 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
|
||||
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;
|
||||
import org.alfresco.repo.domain.NodeStatus;
|
||||
import org.alfresco.repo.domain.PropertyValue;
|
||||
import org.alfresco.repo.domain.Store;
|
||||
@@ -41,18 +44,23 @@ import org.alfresco.service.namespace.QName;
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class NodeImpl implements Node
|
||||
public class NodeImpl extends LifecycleAdapter implements Node
|
||||
{
|
||||
private NodeKey key;
|
||||
private Long id;
|
||||
private Store store;
|
||||
private String uuid;
|
||||
private QName typeQName;
|
||||
private NodeStatus status;
|
||||
// private NodeStatus status;
|
||||
private Set<QName> aspects;
|
||||
private Collection<NodeAssoc> sourceNodeAssocs;
|
||||
private Collection<NodeAssoc> targetNodeAssocs;
|
||||
private Collection<ChildAssoc> parentAssocs;
|
||||
private Collection<ChildAssoc> childAssocs;
|
||||
private Map<QName, PropertyValue> properties;
|
||||
private DbAccessControlList accessControlList;
|
||||
|
||||
private transient ReadLock refReadLock;
|
||||
private transient WriteLock refWriteLock;
|
||||
private transient NodeRef nodeRef;
|
||||
|
||||
public NodeImpl()
|
||||
@@ -63,6 +71,53 @@ public class NodeImpl implements Node
|
||||
parentAssocs = new ArrayList<ChildAssoc>(3);
|
||||
childAssocs = new ArrayList<ChildAssoc>(3);
|
||||
properties = new HashMap<QName, PropertyValue>(5);
|
||||
|
||||
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
refReadLock = lock.readLock();
|
||||
refWriteLock = lock.writeLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread-safe caching of the reference is provided
|
||||
*/
|
||||
public NodeRef getNodeRef()
|
||||
{
|
||||
// first check if it is available
|
||||
refReadLock.lock();
|
||||
try
|
||||
{
|
||||
if (nodeRef != null)
|
||||
{
|
||||
return nodeRef;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
refReadLock.unlock();
|
||||
}
|
||||
// get write lock
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
// double check
|
||||
if (nodeRef == null )
|
||||
{
|
||||
nodeRef = new NodeRef(getStore().getStoreRef(), getUuid());
|
||||
}
|
||||
return nodeRef;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getNodeRef()
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return getNodeRef().toString();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj)
|
||||
@@ -80,31 +135,77 @@ public class NodeImpl implements Node
|
||||
return false;
|
||||
}
|
||||
Node that = (Node) obj;
|
||||
return (this.getKey().equals(that.getKey()));
|
||||
return (this.getNodeRef().equals(that.getNodeRef()));
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return getKey().hashCode();
|
||||
return getNodeRef().hashCode();
|
||||
}
|
||||
|
||||
public NodeKey getKey() {
|
||||
return key;
|
||||
}
|
||||
// @Override
|
||||
// public boolean onDelete(Session session) throws CallbackException
|
||||
// {
|
||||
// // check if there is an access control list
|
||||
// DbAccessControlList acl = getAccessControlList();
|
||||
// if (acl != null)
|
||||
// {
|
||||
// session.delete(acl);
|
||||
// }
|
||||
// return NO_VETO;
|
||||
// }
|
||||
//
|
||||
|
||||
public Long getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* For Hibernate use
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(Long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setKey(NodeKey key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public Store getStore()
|
||||
{
|
||||
return store;
|
||||
}
|
||||
|
||||
public synchronized void setStore(Store store)
|
||||
public void setStore(Store store)
|
||||
{
|
||||
this.store = store;
|
||||
this.nodeRef = null;
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.store = store;
|
||||
this.nodeRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUuid()
|
||||
{
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.uuid = uuid;
|
||||
this.nodeRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public QName getTypeQName()
|
||||
@@ -117,16 +218,16 @@ public class NodeImpl implements Node
|
||||
this.typeQName = typeQName;
|
||||
}
|
||||
|
||||
public NodeStatus getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(NodeStatus status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
// public NodeStatus getStatus()
|
||||
// {
|
||||
// return status;
|
||||
// }
|
||||
//
|
||||
// public void setStatus(NodeStatus status)
|
||||
// {
|
||||
// this.status = status;
|
||||
// }
|
||||
//
|
||||
public Set<QName> getAspects()
|
||||
{
|
||||
return aspects;
|
||||
@@ -211,23 +312,17 @@ public class NodeImpl implements Node
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread-safe caching of the reference is provided
|
||||
*/
|
||||
public synchronized NodeRef getNodeRef()
|
||||
public DbAccessControlList getAccessControlList()
|
||||
{
|
||||
if (nodeRef == null && key != null)
|
||||
{
|
||||
nodeRef = new NodeRef(getStore().getStoreRef(), getKey().getGuid());
|
||||
}
|
||||
return nodeRef;
|
||||
return accessControlList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see #getNodeRef()
|
||||
* For Hibernate use
|
||||
*/
|
||||
public String toString()
|
||||
@SuppressWarnings("unused")
|
||||
private void setAccessControlList(DbAccessControlList accessControlList)
|
||||
{
|
||||
return getNodeRef().toString();
|
||||
this.accessControlList = accessControlList;
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package org.alfresco.repo.domain.hibernate;
|
||||
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.repo.domain.NodeKey;
|
||||
import org.alfresco.repo.domain.NodeStatus;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
@@ -28,8 +29,19 @@ import org.alfresco.util.EqualsHelper;
|
||||
public class NodeStatusImpl implements NodeStatus
|
||||
{
|
||||
private NodeKey key;
|
||||
private Node node;
|
||||
private String changeTxnId;
|
||||
private boolean deleted;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(50);
|
||||
sb.append("NodeStatus")
|
||||
.append("[key=").append(key)
|
||||
.append(", node=").append(node == null ? null : node.getNodeRef())
|
||||
.append(", txn=").append(changeTxnId)
|
||||
.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
@@ -45,23 +57,10 @@ public class NodeStatusImpl implements NodeStatus
|
||||
else if (!(obj instanceof NodeStatusImpl))
|
||||
return false;
|
||||
NodeStatus that = (NodeStatus) obj;
|
||||
return (EqualsHelper.nullSafeEquals(this.key, that.getKey())) &&
|
||||
(EqualsHelper.nullSafeEquals(this.changeTxnId, that.getChangeTxnId())) &&
|
||||
(this.deleted == that.isDeleted());
|
||||
return (EqualsHelper.nullSafeEquals(this.key, that.getKey()));
|
||||
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(50);
|
||||
sb.append("NodeStatus")
|
||||
.append("[key=").append(key)
|
||||
.append(", txn=").append(changeTxnId)
|
||||
.append(", deleted=").append(deleted)
|
||||
.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public NodeKey getKey()
|
||||
{
|
||||
return key;
|
||||
@@ -72,6 +71,16 @@ public class NodeStatusImpl implements NodeStatus
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public Node getNode()
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
public void setNode(Node node)
|
||||
{
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public String getChangeTxnId()
|
||||
{
|
||||
return changeTxnId;
|
||||
@@ -84,11 +93,15 @@ public class NodeStatusImpl implements NodeStatus
|
||||
|
||||
public boolean isDeleted()
|
||||
{
|
||||
return deleted;
|
||||
return (node == null);
|
||||
}
|
||||
|
||||
public void setDeleted(boolean deleted)
|
||||
/**
|
||||
* For Hibernate use
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setDeleted(boolean deleted)
|
||||
{
|
||||
this.deleted = deleted;
|
||||
// this is a convenience, derived property
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,200 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
'-//Hibernate/Hibernate Mapping DTD 3.0//EN'
|
||||
'http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd'>
|
||||
|
||||
<hibernate-mapping>
|
||||
<class
|
||||
name="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl"
|
||||
proxy="org.alfresco.repo.domain.DbAccessControlList"
|
||||
table="access_control_list"
|
||||
dynamic-insert="false"
|
||||
dynamic-update="false"
|
||||
select-before-update="false"
|
||||
lazy="true"
|
||||
optimistic-lock="version" >
|
||||
|
||||
<id name="id" column="id" type="long" >
|
||||
<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>
|
||||
|
||||
<property name="inherits" column="inherits" type="boolean" not-null="true" />
|
||||
|
||||
</class>
|
||||
|
||||
<class
|
||||
name="org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl"
|
||||
proxy="org.alfresco.repo.domain.DbAccessControlEntry"
|
||||
table="access_control_entry"
|
||||
dynamic-insert="false"
|
||||
dynamic-update="false"
|
||||
select-before-update="false"
|
||||
lazy="true"
|
||||
optimistic-lock="version" >
|
||||
|
||||
<id name="id" column="id" type="long" >
|
||||
<generator class="native" />
|
||||
</id>
|
||||
|
||||
<natural-id mutable="true" >
|
||||
<many-to-one
|
||||
name="accessControlList"
|
||||
class="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl"
|
||||
column="acl_id"
|
||||
lazy="no-proxy"
|
||||
fetch="select"
|
||||
optimistic-lock="true"
|
||||
not-null="true" />
|
||||
<many-to-one
|
||||
name="permission"
|
||||
class="org.alfresco.repo.domain.hibernate.DbPermissionImpl"
|
||||
column="permission_id"
|
||||
lazy="no-proxy"
|
||||
fetch="select"
|
||||
optimistic-lock="true"
|
||||
not-null="true" />
|
||||
<many-to-one
|
||||
name="authority"
|
||||
class="org.alfresco.repo.domain.hibernate.DbAuthorityImpl"
|
||||
column="authority_id"
|
||||
lazy="no-proxy"
|
||||
fetch="select"
|
||||
optimistic-lock="true"
|
||||
not-null="true" />
|
||||
</natural-id>
|
||||
|
||||
<property name="allowed" column="allowed" type="boolean" not-null="true" />
|
||||
|
||||
</class>
|
||||
|
||||
<class
|
||||
name="org.alfresco.repo.domain.hibernate.DbPermissionImpl"
|
||||
proxy="org.alfresco.repo.domain.DbPermission"
|
||||
table="permission"
|
||||
dynamic-insert="false"
|
||||
dynamic-update="false"
|
||||
select-before-update="false"
|
||||
lazy="true"
|
||||
optimistic-lock="version" >
|
||||
|
||||
<id name="id" column="id" type="long" >
|
||||
<generator class="native" />
|
||||
</id>
|
||||
|
||||
<natural-id mutable="true">
|
||||
<property name="typeQname" column="type_qname" type="QName" length="200" />
|
||||
<property name="name" type="string" length="100" column="name" />
|
||||
</natural-id>
|
||||
|
||||
</class>
|
||||
|
||||
<class
|
||||
name="org.alfresco.repo.domain.hibernate.DbAuthorityImpl"
|
||||
proxy="org.alfresco.repo.domain.DbAuthority"
|
||||
table="authority"
|
||||
dynamic-insert="false"
|
||||
dynamic-update="false"
|
||||
select-before-update="false"
|
||||
lazy="true"
|
||||
optimistic-lock="version" >
|
||||
|
||||
<id name="recipient" column="recipient" type="string" length="100" />
|
||||
|
||||
<set
|
||||
name="externalKeys"
|
||||
table="auth_ext_keys"
|
||||
lazy="true"
|
||||
sort="unsorted"
|
||||
fetch="select"
|
||||
optimistic-lock="true" >
|
||||
<key >
|
||||
<column name="id" />
|
||||
</key>
|
||||
<element column="externalKey" length="100" not-null="true" type="string" />
|
||||
</set>
|
||||
</class>
|
||||
|
||||
<query name="permission.GetPermission" cacheable="true">
|
||||
select distinct
|
||||
permission
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.DbPermissionImpl as permission
|
||||
where
|
||||
permission.typeQname = :permissionTypeQName and
|
||||
permission.name = :permissionName
|
||||
</query>
|
||||
|
||||
<query name="permission.GetAccessControlEntriesForAccessControlList" cacheable="true" >
|
||||
select
|
||||
ace
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl as ace
|
||||
where
|
||||
ace.accessControlList.id = :accessControlListId
|
||||
</query>
|
||||
|
||||
<query name="permission.GetAccessControlEntriesForPermission">
|
||||
select
|
||||
ace
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl as ace
|
||||
where
|
||||
ace.permission.id = :permissionId
|
||||
</query>
|
||||
|
||||
<query name="permission.GetAccessControlEntriesForAuthority">
|
||||
select
|
||||
ace
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl as ace
|
||||
where
|
||||
ace.authority.recipient = :authorityRecipient
|
||||
</query>
|
||||
|
||||
<query name="permission.GetAccessControlEntriesForAuthorityAndNode">
|
||||
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
|
||||
</query>
|
||||
|
||||
<query name="permission.GetAccessControlEntryForAll">
|
||||
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
|
||||
</query>
|
||||
|
||||
<query name="permission.GetAccessControlListForNode" cacheable="true" >
|
||||
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
|
||||
</query>
|
||||
|
||||
</hibernate-mapping>
|
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
* 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.hibernate;
|
||||
|
||||
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.Node;
|
||||
import org.alfresco.repo.node.db.NodeDaoService;
|
||||
import org.alfresco.repo.security.permissions.NodePermissionEntry;
|
||||
import org.alfresco.repo.security.permissions.PermissionEntry;
|
||||
import org.alfresco.repo.security.permissions.PermissionReference;
|
||||
import org.alfresco.repo.security.permissions.impl.PermissionsDaoComponent;
|
||||
import org.alfresco.repo.security.permissions.impl.SimpleNodePermissionEntry;
|
||||
import org.alfresco.repo.security.permissions.impl.SimplePermissionEntry;
|
||||
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
|
||||
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;
|
||||
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
|
||||
|
||||
/**
|
||||
* Support for accessing persisted permission information.
|
||||
*
|
||||
* This class maps between persisted objects and the external API defined in the
|
||||
* PermissionsDAO interface.
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements PermissionsDaoComponent
|
||||
{
|
||||
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<NodeRef, SimpleNodePermissionEntry> nullPermissionCache;
|
||||
|
||||
public PermissionsDaoComponentImpl()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public void setNodeDaoService(NodeDaoService nodeDaoService)
|
||||
{
|
||||
this.nodeDaoService = nodeDaoService;
|
||||
}
|
||||
|
||||
public void setNullPermissionCache(SimpleCache<NodeRef, SimpleNodePermissionEntry> nullPermissionCache)
|
||||
{
|
||||
this.nullPermissionCache = nullPermissionCache;
|
||||
}
|
||||
|
||||
public NodePermissionEntry getPermissions(NodeRef nodeRef)
|
||||
{
|
||||
// Create the object if it is not found.
|
||||
// Null objects are not cached in hibernate
|
||||
// If the object does not exist it will repeatedly query to check its
|
||||
// non existence.
|
||||
|
||||
NodePermissionEntry npe = nullPermissionCache.get(nodeRef);
|
||||
if (npe != null)
|
||||
{
|
||||
return npe;
|
||||
}
|
||||
// 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.<SimplePermissionEntry> emptySet());
|
||||
npe = snpe;
|
||||
nullPermissionCache.put(nodeRef, snpe);
|
||||
}
|
||||
else
|
||||
{
|
||||
npe = createSimpleNodePermissionEntry(acl);
|
||||
}
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Created access control list for node: " + nodeRef);
|
||||
}
|
||||
return npe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the persisted access control list or create it if required.
|
||||
*
|
||||
* @param nodeRef - the node for which to create the list
|
||||
* @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)
|
||||
{
|
||||
// get the access control list for the node
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
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<DbAccessControlList> results = (List<DbAccessControlList>) getHibernateTemplate().execute(callback);
|
||||
DbAccessControlList acl = null;
|
||||
if (results.size() == 0)
|
||||
{
|
||||
// we'll return null
|
||||
}
|
||||
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);
|
||||
}
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Retrieved access control list: \n" +
|
||||
" node: " + nodeRef + "\n" +
|
||||
" list: " + acl);
|
||||
}
|
||||
return acl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an access control list for the node and removes the entry from
|
||||
* the nullPermsionCache.
|
||||
*/
|
||||
private DbAccessControlList createAccessControlList(final NodeRef nodeRef)
|
||||
{
|
||||
// get the node referenced
|
||||
Node node = getNode(nodeRef);
|
||||
|
||||
DbAccessControlList acl = new DbAccessControlListImpl();
|
||||
acl.setNode(node);
|
||||
acl.setInherits(true);
|
||||
getHibernateTemplate().save(acl);
|
||||
|
||||
nullPermissionCache.remove(nodeRef);
|
||||
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Created Access Control List: \n" +
|
||||
" node: " + nodeRef + "\n" +
|
||||
" list: " + acl);
|
||||
}
|
||||
return acl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeRef the node reference
|
||||
* @return Returns the node for the given reference, or null
|
||||
*/
|
||||
private Node getNode(NodeRef nodeRef)
|
||||
{
|
||||
Node node = nodeDaoService.getNode(nodeRef);
|
||||
if (node == null)
|
||||
{
|
||||
throw new InvalidNodeRefException(nodeRef);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
public void deletePermissions(NodeRef nodeRef)
|
||||
{
|
||||
DbAccessControlList acl = getAccessControlList(nodeRef, false);
|
||||
if (acl != null)
|
||||
{
|
||||
// delete the access control list - it will cascade to the entries
|
||||
getHibernateTemplate().delete(acl);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void deletePermissions(final String authority)
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
public Object doInHibernate(Session session)
|
||||
{
|
||||
Query query = session
|
||||
.getNamedQuery(QUERY_GET_AC_ENTRIES_FOR_AUTHORITY)
|
||||
.setString("authorityRecipient", authority);
|
||||
return (Integer) HibernateHelper.deleteQueryResults(session, query);
|
||||
}
|
||||
};
|
||||
Integer deletedCount = (Integer) getHibernateTemplate().execute(callback);
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Deleted " + deletedCount + " entries for authority " + authority);
|
||||
}
|
||||
}
|
||||
|
||||
public void deletePermissions(final NodeRef nodeRef, final String authority)
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
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);
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Deleted " + deletedCount + "entries for criteria: \n" +
|
||||
" node: " + nodeRef + "\n" +
|
||||
" authority: " + authority);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all permission entries (access control list entries) that match
|
||||
* 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)
|
||||
{
|
||||
// get the entry
|
||||
DbAccessControlEntry entry = getAccessControlEntry(nodeRef, authority, permission);
|
||||
if (entry != null)
|
||||
{
|
||||
getHibernateTemplate().delete(entry);
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Deleted entry for criteria: \n" +
|
||||
" node: " + nodeRef + "\n" +
|
||||
" authority: " + authority + "\n" +
|
||||
" permission: " + permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPermission(NodeRef nodeRef, String authority, PermissionReference permission, boolean allow)
|
||||
{
|
||||
// get the entry
|
||||
DbAccessControlEntry entry = getAccessControlEntry(nodeRef, authority, permission);
|
||||
if (entry == null)
|
||||
{
|
||||
// need to create it
|
||||
DbAccessControlList dbAccessControlList = getAccessControlList(nodeRef, 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);
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Created new access control entry: " + entry);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.setAllowed(allow);
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Updated access control entry: " + entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeRef the node against which to join
|
||||
* @param authority the authority against which to join
|
||||
* @param perm the permission against which to join
|
||||
* @return Returns all access control entries that match the criteria
|
||||
*/
|
||||
private DbAccessControlEntry getAccessControlEntry(
|
||||
final NodeRef nodeRef,
|
||||
final String authority,
|
||||
final PermissionReference permission)
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
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);
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("" + (entry == null ? "Did not find" : "Found") + "entry for criteria: \n" +
|
||||
" node: " + nodeRef + "\n" +
|
||||
" authority: " + authority + "\n" +
|
||||
" permission: " + permission);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to find or create a persisted authority
|
||||
*/
|
||||
private DbAuthority getAuthority(String authority, boolean create)
|
||||
{
|
||||
DbAuthority entity = (DbAuthority) getHibernateTemplate().get(DbAuthorityImpl.class, authority);
|
||||
if ((entity == null) && create)
|
||||
{
|
||||
entity = new DbAuthorityImpl();
|
||||
entity.setRecipient(authority);
|
||||
getHibernateTemplate().save(entity);
|
||||
return entity;
|
||||
}
|
||||
else
|
||||
{
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to find and optionally create a persisted permission.
|
||||
*/
|
||||
private DbPermission getPermission(PermissionReference permissionRef, final boolean create)
|
||||
{
|
||||
final QName qname = permissionRef.getQName();
|
||||
final String name = permissionRef.getName();
|
||||
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
public Object doInHibernate(Session session)
|
||||
{
|
||||
return DbPermissionImpl.find(session, qname, name);
|
||||
}
|
||||
};
|
||||
DbPermission dbPermission = (DbPermission) getHibernateTemplate().execute(callback);
|
||||
|
||||
// create if necessary
|
||||
if ((dbPermission == null) && create)
|
||||
{
|
||||
dbPermission = new DbPermissionImpl();
|
||||
dbPermission.setTypeQname(qname);
|
||||
dbPermission.setName(name);
|
||||
getHibernateTemplate().save(dbPermission);
|
||||
}
|
||||
return dbPermission;
|
||||
}
|
||||
|
||||
public void setPermission(PermissionEntry permissionEntry)
|
||||
{
|
||||
setPermission(
|
||||
permissionEntry.getNodeRef(),
|
||||
permissionEntry.getAuthority(),
|
||||
permissionEntry.getPermissionReference(),
|
||||
permissionEntry.isAllowed());
|
||||
}
|
||||
|
||||
public void setPermission(NodePermissionEntry nodePermissionEntry)
|
||||
{
|
||||
NodeRef nodeRef = nodePermissionEntry.getNodeRef();
|
||||
// get the access control list
|
||||
DbAccessControlList acl = getAccessControlList(nodeRef, 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();
|
||||
}
|
||||
// set attributes
|
||||
acl.setInherits(nodePermissionEntry.inheritPermissions());
|
||||
|
||||
// add all entries
|
||||
for (PermissionEntry pe : nodePermissionEntry.getPermissionEntries())
|
||||
{
|
||||
PermissionReference permission = pe.getPermissionReference();
|
||||
String authority = pe.getAuthority();
|
||||
boolean isAllowed = pe.isAllowed();
|
||||
|
||||
DbPermission permissionEntity = getPermission(permission, true);
|
||||
DbAuthority authorityEntity = getAuthority(authority, true);
|
||||
|
||||
DbAccessControlEntryImpl entry = DbAccessControlEntryImpl.create(
|
||||
acl,
|
||||
permissionEntity,
|
||||
authorityEntity,
|
||||
isAllowed);
|
||||
getHibernateTemplate().save(entry);
|
||||
}
|
||||
}
|
||||
|
||||
public void setInheritParentPermissions(NodeRef nodeRef, boolean inheritParentPermissions)
|
||||
{
|
||||
DbAccessControlList acl = getAccessControlList(nodeRef, true);
|
||||
acl.setInherits(inheritParentPermissions);
|
||||
}
|
||||
|
||||
public boolean getInheritParentPermissions(NodeRef nodeRef)
|
||||
{
|
||||
DbAccessControlList acl = getAccessControlList(nodeRef, false);
|
||||
if (acl == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return acl.getInherits();
|
||||
}
|
||||
}
|
||||
|
||||
// Utility methods to create simple detached objects for the outside world
|
||||
// We do not pass out the hibernate objects
|
||||
|
||||
private SimpleNodePermissionEntry createSimpleNodePermissionEntry(DbAccessControlList acl)
|
||||
{
|
||||
if (acl == null)
|
||||
{
|
||||
ParameterCheck.mandatory("acl", acl);
|
||||
}
|
||||
List<DbAccessControlEntry> entries = getEntriesForList(acl);
|
||||
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<DbAccessControlEntry> 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<DbAccessControlEntry> entries = (List<DbAccessControlEntry>) 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<SimplePermissionEntry> createSimplePermissionEntries(List<DbAccessControlEntry> entries)
|
||||
{
|
||||
if (entries == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
HashSet<SimplePermissionEntry> spes = new HashSet<SimplePermissionEntry>(entries.size(), 1.0f);
|
||||
if (entries.size() != 0)
|
||||
{
|
||||
for (DbAccessControlEntry entry : entries)
|
||||
{
|
||||
spes.add(createSimplePermissionEntry(entry));
|
||||
}
|
||||
}
|
||||
return spes;
|
||||
}
|
||||
|
||||
private static SimplePermissionEntry createSimplePermissionEntry(DbAccessControlEntry ace)
|
||||
{
|
||||
if (ace == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new SimplePermissionEntry(
|
||||
ace.getAccessControlList().getNode().getNodeRef(),
|
||||
createSimplePermissionReference(ace.getPermission()),
|
||||
ace.getAuthority().getRecipient(),
|
||||
ace.isAllowed() ? AccessStatus.ALLOWED : AccessStatus.DENIED);
|
||||
}
|
||||
|
||||
private static SimplePermissionReference createSimplePermissionReference(DbPermission perm)
|
||||
{
|
||||
if (perm == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new SimplePermissionReference(
|
||||
perm.getTypeQname(),
|
||||
perm.getName());
|
||||
}
|
||||
}
|
@@ -22,13 +22,11 @@
|
||||
<!-- forward assoc to root node -->
|
||||
<many-to-one
|
||||
name="rootNode"
|
||||
not-null="false"
|
||||
not-null="true"
|
||||
lazy="false"
|
||||
class="org.alfresco.repo.domain.hibernate.NodeImpl"
|
||||
fetch="join" >
|
||||
<column name="root_protocol" />
|
||||
<column name="root_identifier" />
|
||||
<column name="root_guid" />
|
||||
<column name="root_node_id" />
|
||||
</many-to-one>
|
||||
</class>
|
||||
|
||||
|
@@ -16,6 +16,10 @@
|
||||
*/
|
||||
package org.alfresco.repo.domain.hibernate;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.repo.domain.Store;
|
||||
import org.alfresco.repo.domain.StoreKey;
|
||||
@@ -30,10 +34,59 @@ public class StoreImpl implements Store
|
||||
{
|
||||
private StoreKey key;
|
||||
private Node rootNode;
|
||||
|
||||
private transient ReadLock refReadLock;
|
||||
private transient WriteLock refWriteLock;
|
||||
private transient StoreRef storeRef;
|
||||
|
||||
public StoreImpl()
|
||||
{
|
||||
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
refReadLock = lock.readLock();
|
||||
refWriteLock = lock.writeLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily constructs <code>StoreRef</code> instance referencing this entity
|
||||
*/
|
||||
public StoreRef getStoreRef()
|
||||
{
|
||||
// first check if it is available
|
||||
refReadLock.lock();
|
||||
try
|
||||
{
|
||||
if (storeRef != null)
|
||||
{
|
||||
return storeRef;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
refReadLock.unlock();
|
||||
}
|
||||
// get write lock
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
// double check
|
||||
if (storeRef == null )
|
||||
{
|
||||
storeRef = new StoreRef(getKey().getProtocol(), getKey().getIdentifier());
|
||||
}
|
||||
return storeRef;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getStoreRef()()
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return getStoreRef().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,11 +102,11 @@ public class StoreImpl implements Store
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (!(obj instanceof Node))
|
||||
else if (!(obj instanceof Store))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Node that = (Node) obj;
|
||||
Store that = (Store) obj;
|
||||
return (this.getKey().equals(that.getKey()));
|
||||
}
|
||||
|
||||
@@ -65,42 +118,32 @@ public class StoreImpl implements Store
|
||||
return getKey().hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getStoreRef()()
|
||||
*/
|
||||
public String toString()
|
||||
public StoreKey getKey()
|
||||
{
|
||||
return getStoreRef().toString();
|
||||
return key;
|
||||
}
|
||||
|
||||
public StoreKey getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public synchronized void setKey(StoreKey key) {
|
||||
this.key = key;
|
||||
this.storeRef = null;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void setKey(StoreKey key)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.key = key;
|
||||
this.storeRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Node getRootNode()
|
||||
{
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
|
||||
public void setRootNode(Node rootNode)
|
||||
{
|
||||
this.rootNode = rootNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily constructs <code>StoreRef</code> instance referencing this entity
|
||||
*/
|
||||
public synchronized StoreRef getStoreRef()
|
||||
{
|
||||
if (storeRef == null && key != null)
|
||||
{
|
||||
storeRef = new StoreRef(key.getProtocol(), key.getIdentifier());
|
||||
}
|
||||
return storeRef;
|
||||
}
|
||||
}
|
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package org.alfresco.repo.domain.hibernate;
|
||||
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.repo.domain.StoreKey;
|
||||
import org.alfresco.repo.domain.VersionCount;
|
||||
|
||||
@@ -50,11 +49,11 @@ public class VersionCountImpl implements VersionCount
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (!(obj instanceof Node))
|
||||
else if (!(obj instanceof VersionCount))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Node that = (Node) obj;
|
||||
VersionCount that = (VersionCount) obj;
|
||||
return (this.getKey().equals(that.getKey()));
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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.hibernate;
|
||||
|
||||
import org.alfresco.repo.domain.StoreKey;
|
||||
import org.alfresco.repo.domain.VersionCount;
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.version.common.counter.VersionCounterService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.hibernate.LockMode;
|
||||
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
|
||||
|
||||
/**
|
||||
* Version counter DAO service implemtation using Hibernate.
|
||||
* <p>
|
||||
* The object should execute within its own transaction, and is limited to single-thread
|
||||
* entry. If it becomes a bottleneck, the transaction synchronization should be moved
|
||||
* over to reentrant locks and/or the hibernate mappings should be optimized for better
|
||||
* read-write access.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class VersionCounterDaoComponentImpl
|
||||
extends HibernateDaoSupport
|
||||
implements VersionCounterService, NodeServicePolicies.BeforeCreateStorePolicy
|
||||
{
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
/**
|
||||
* @param policyComponent the component to register behaviour
|
||||
*/
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to receive notifications of store creations
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeCreateStore"),
|
||||
this,
|
||||
new JavaBehaviour(this, "beforeCreateStore"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a version counter for the store
|
||||
* @param nodeTypeQName
|
||||
* @param storeRef
|
||||
*/
|
||||
public void beforeCreateStore(QName nodeTypeQName, StoreRef storeRef)
|
||||
{
|
||||
final StoreKey storeKey = new StoreKey(storeRef.getProtocol(), storeRef.getIdentifier());
|
||||
VersionCount versionCount = (VersionCount) getHibernateTemplate().get(VersionCountImpl.class, storeKey);
|
||||
if (versionCount != null)
|
||||
{
|
||||
// already exists
|
||||
return;
|
||||
}
|
||||
versionCount = new VersionCountImpl();
|
||||
versionCount.setKey(storeKey);
|
||||
getHibernateTemplate().save(versionCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves or creates a version counter. This locks the counter against updates for the
|
||||
* current transaction.
|
||||
*
|
||||
* @param storeKey the primary key of the counter
|
||||
* @return Returns a current or new version counter
|
||||
*/
|
||||
private VersionCount getVersionCounter(StoreRef storeRef)
|
||||
{
|
||||
final StoreKey storeKey = new StoreKey(storeRef.getProtocol(), storeRef.getIdentifier());
|
||||
|
||||
// check if it exists
|
||||
VersionCount versionCount = (VersionCount) getHibernateTemplate().get(
|
||||
VersionCountImpl.class,
|
||||
storeKey,
|
||||
LockMode.UPGRADE);
|
||||
if (versionCount == null)
|
||||
{
|
||||
// This could fail on some databases with concurrent adds. But it is only those databases
|
||||
// that don't lock the index against an addition of the row, and then it will only fail once.
|
||||
versionCount = new VersionCountImpl();
|
||||
versionCount.setKey(storeKey);
|
||||
getHibernateTemplate().save(versionCount);
|
||||
// debug
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Created version counter: \n" +
|
||||
" Thread: " + Thread.currentThread().getName() + "\n" +
|
||||
" Version count: " + versionCount.getVersionCount());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// debug
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Got version counter: \n" +
|
||||
" Thread: " + Thread.currentThread().getName() + "\n" +
|
||||
" Version count: " + versionCount.getVersionCount());
|
||||
}
|
||||
}
|
||||
// done
|
||||
return versionCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next available version number for the specified store.
|
||||
*
|
||||
* @param storeRef the version store id
|
||||
* @return the next version number
|
||||
*/
|
||||
public int nextVersionNumber(StoreRef storeRef)
|
||||
{
|
||||
// get the version counter
|
||||
VersionCount versionCount = getVersionCounter(storeRef);
|
||||
// get an incremented count
|
||||
int nextCount = versionCount.incrementVersionCount();
|
||||
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Incremented version count: \n" +
|
||||
" Thread: " + Thread.currentThread().getName() + "\n" +
|
||||
" New version count: " + versionCount.getVersionCount());
|
||||
}
|
||||
return nextCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current version number for the specified store.
|
||||
*
|
||||
* @param storeRef the store reference
|
||||
* @return the current version number, zero if no version yet allocated.
|
||||
*/
|
||||
public int currentVersionNumber(StoreRef storeRef)
|
||||
{
|
||||
// get the version counter
|
||||
VersionCount versionCounter = getVersionCounter(storeRef);
|
||||
// get an incremented count
|
||||
return versionCounter.getVersionCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the version number for a the specified store.
|
||||
*
|
||||
* WARNING: calling this method will completely reset the current
|
||||
* version count for the specified store and cannot be undone.
|
||||
*
|
||||
* @param storeRef the store reference
|
||||
*/
|
||||
public synchronized void resetVersionNumber(StoreRef storeRef)
|
||||
{
|
||||
// get the version counter
|
||||
VersionCount versionCounter = getVersionCounter(storeRef);
|
||||
// get an incremented count
|
||||
versionCounter.resetVersionCount();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user