diff --git a/config/alfresco/avm-services-context.xml b/config/alfresco/avm-services-context.xml index 9a8a048ba6..3d30520a9e 100644 --- a/config/alfresco/avm-services-context.xml +++ b/config/alfresco/avm-services-context.xml @@ -4,54 +4,6 @@ - - - - - node - - - - - - - - - - - - - - - layer - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -113,9 +65,6 @@ - - - @@ -186,12 +135,6 @@ - - - - - - diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index bdef462051..28d13be08a 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -95,6 +95,7 @@ + @@ -118,12 +119,6 @@ - - - - - - diff --git a/config/alfresco/dbscripts/upgrade/3.2/org.hibernate.dialect.MySQLInnoDBDialect/remove-AVM-issuer.sql b/config/alfresco/dbscripts/upgrade/3.2/org.hibernate.dialect.MySQLInnoDBDialect/remove-AVM-issuer.sql new file mode 100644 index 0000000000..1a717b86fe --- /dev/null +++ b/config/alfresco/dbscripts/upgrade/3.2/org.hibernate.dialect.MySQLInnoDBDialect/remove-AVM-issuer.sql @@ -0,0 +1,53 @@ +-- +-- Title: Upgrade to V3.2 - Remove AVM Issuer +-- Database: MySQL +-- Since: V3.2 schema X +-- Author: janv +-- +-- remove AVM node issuer - replace with auto-increment id +-- +-- Please contact support@alfresco.com if you need assistance with the upgrade. +-- + +-- ----------------------------- +-- Enable auto-increment -- +-- ----------------------------- + +insert into avm_nodes +select +(select max(id)+1 from avm_nodes), +class_type, vers, version_id, guid, creator, owner, lastModifier, createDate, modDate, accessDate, is_root, store_new_id, acl_id, deletedType, layer_id, indirection, indirection_version, primary_indirection, opacity, content_url, mime_type, encoding, length +from avm_nodes where id = 0; + +update avm_aspects set node_id = (select max(id) from avm_nodes) where node_id = 0; + +update avm_child_entries set parent_id = (select max(id) from avm_nodes) where parent_id = 0; +update avm_child_entries set child_id = (select max(id) from avm_nodes) where child_id = 0; + +update avm_history_links set ancestor = (select max(id) from avm_nodes) where ancestor = 0; +update avm_history_links set descendent = (select max(id) from avm_nodes) where descendent = 0; + +update avm_merge_links set mfrom = (select max(id) from avm_nodes) where mfrom = 0; +update avm_merge_links set mto = (select max(id) from avm_nodes) where mto = 0; + +update avm_node_properties set node_id = (select max(id) from avm_nodes) where node_id = 0; + +update avm_stores set current_root_id = (select max(id) from avm_nodes) where current_root_id = 0; + +update avm_version_roots set root_id = (select max(id) from avm_nodes) where root_id = 0; + +delete from avm_nodes where id = 0; + +alter table avm_nodes modify column id bigint not null auto_increment; + +-- +-- Record script finish +-- +DELETE FROM alf_applied_patch WHERE id = 'patch.db-V3.2-Remove-AVM-Issuer'; +INSERT INTO alf_applied_patch + (id, description, fixes_from_schema, fixes_to_schema, applied_to_schema, target_schema, applied_on_date, applied_to_server, was_executed, succeeded, report) + VALUES + ( + 'patch.db-V3.2-Remove-AVM-Issuer', 'Manually executed script upgrade V3.2 to remove AVM Issuer', + 0, 2007, -1, 2008, null, 'UNKOWN', 1, 1, 'Script completed' + ); diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml index 7f42569e90..162329b4d6 100644 --- a/config/alfresco/patch/patch-services-context.xml +++ b/config/alfresco/patch/patch-services-context.xml @@ -1759,5 +1759,15 @@ + + patch.db-V3.2-Remove-AVM-Issuer + patch.schemaUpgradeScript.description + 0 + 2007 + 2008 + + classpath:alfresco/dbscripts/upgrade/3.2/${db.script.dialect}/remove-AVM-issuer.sql + + diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties index e9f9595b33..cbb62f2360 100644 --- a/config/alfresco/version.properties +++ b/config/alfresco/version.properties @@ -19,4 +19,4 @@ version.build=@build-number@ # Schema number -version.schema=2007 +version.schema=2008 diff --git a/source/java/org/alfresco/repo/avm/AVMDAOs.java b/source/java/org/alfresco/repo/avm/AVMDAOs.java index d42812fef9..2a08d5b2a8 100644 --- a/source/java/org/alfresco/repo/avm/AVMDAOs.java +++ b/source/java/org/alfresco/repo/avm/AVMDAOs.java @@ -1,6 +1,26 @@ -/** - * - */ +/* + * Copyright (C) 2005-2009 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" */ + package org.alfresco.repo.avm; import org.alfresco.repo.attributes.AttributeDAO; @@ -34,11 +54,6 @@ public class AVMDAOs return fgInstance; } - /** - * The IssuerDAO. - */ - public IssuerDAO fIssuerDAO; - /** * The AVMNodeDAO. */ @@ -141,14 +156,6 @@ public class AVMDAOs { fVersionRootDAO = versionRootDAO; } - - /** - * @param issuerDAO the fIssuerDAO to set - */ - public void setIssuerDAO(IssuerDAO issuerDAO) - { - fIssuerDAO = issuerDAO; - } public void setAvmStorePropertyDAO(AVMStorePropertyDAO avmStorePropertyDAO) { diff --git a/source/java/org/alfresco/repo/avm/AVMNodeImpl.java b/source/java/org/alfresco/repo/avm/AVMNodeImpl.java index 45516440f9..dfdc0a11c1 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeImpl.java @@ -1,543 +1,540 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" */ - -package org.alfresco.repo.avm; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.alfresco.repo.avm.util.RawServices; -import org.alfresco.repo.domain.DbAccessControlList; -import org.alfresco.repo.domain.PropertyValue; -import org.alfresco.repo.security.permissions.ACLCopyMode; -import org.alfresco.service.cmr.avm.AVMReadOnlyException; -import org.alfresco.util.GUID; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Base class for all repository file system like objects. - * @author britt - */ -public abstract class AVMNodeImpl implements AVMNode, Serializable -{ - private static Log fgLogger = LogFactory.getLog(AVMNodeImpl.class); - - protected static final boolean DEBUG = fgLogger.isDebugEnabled(); - - /** - * The Object ID. - */ - private long fID; - - /** - * The Version ID. - */ - private int fVersionID; - - /** - * The basic attributes of this. Owner, creator, mod time, etc. - */ - private BasicAttributes fBasicAttributes; - - /** - * The version number (for concurrency control). - */ - private long fVers; - - /** - * The rootness of this node. - */ - private boolean fIsRoot; - - /** - * The ACL on this node. - */ - private DbAccessControlList fACL; - - /** - * The Store that we're new in. - */ - private AVMStore fStoreNew; - - /** - * The GUID for this version. - */ - private String fGUID; - - /** - * The Aspects that belong to this node. - */ - private Set fAspects; - - private Map fProperties; - - /** - * Default constructor. - */ - protected AVMNodeImpl() - { - fAspects = new HashSet(); - fProperties = new HashMap(); - } - - /** - * Constructor used when creating a new concrete subclass instance. - * @param id The object id. - * @param store The AVMStore that owns this. - */ - protected AVMNodeImpl(long id, - AVMStore store) - { - fAspects = new HashSet(); - fProperties = new HashMap(); - fID = id; - fVersionID = -1; - fIsRoot = false; - long time = System.currentTimeMillis(); - String user = - RawServices.Instance().getAuthenticationComponent().getCurrentUserName(); - if (user == null) - { - user = RawServices.Instance().getAuthenticationComponent().getSystemUserName(); - } - fBasicAttributes = new BasicAttributesImpl(user, - user, - user, - time, - time, - time); - fStoreNew = store; - fGUID = GUID.generate(); - } - - /** - * Set the ancestor of this node. - * @param ancestor The ancestor to set. - */ - public void setAncestor(AVMNode ancestor) - { - if (ancestor == null) - { - return; - } - HistoryLinkImpl link = new HistoryLinkImpl(); - link.setAncestor(ancestor); - link.setDescendent(this); - AVMDAOs.Instance().fHistoryLinkDAO.save(link); - } - - /** - * Change the ancestor of this node. - * @param ancestor The new ancestor to give it. - */ - public void changeAncestor(AVMNode ancestor) - { - HistoryLink old = AVMDAOs.Instance().fHistoryLinkDAO.getByDescendent(this); - if (old != null) - { - AVMDAOs.Instance().fHistoryLinkDAO.delete(old); - } - setAncestor(ancestor); - } - - /** - * Get the ancestor of this node. - * @return The ancestor of this node. - */ - public AVMNode getAncestor() - { - return AVMDAOs.Instance().fAVMNodeDAO.getAncestor(this); - } - - /** - * Set the node that was merged into this. - * @param mergedFrom The node that was merged into this. - */ - public void setMergedFrom(AVMNode mergedFrom) - { - if (mergedFrom == null) - { - return; - } - MergeLinkImpl link = new MergeLinkImpl(); - link.setMfrom(mergedFrom); - link.setMto(this); - AVMDAOs.Instance().fMergeLinkDAO.save(link); - } - - /** - * Get the node that was merged into this. - * @return The node that was merged into this. - */ - public AVMNode getMergedFrom() - { - return AVMDAOs.Instance().fAVMNodeDAO.getMergedFrom(this); - } - - /** - * Equality based on object ids. - * @param obj The thing to compare against. - * @return Equality. - */ - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (!(obj instanceof AVMNode)) - { - return false; - } - return fID == ((AVMNode)obj).getId(); - } - - /** - * Get a reasonable hash value. - * @return The hash code. - */ - @Override - public int hashCode() - { - return (int)fID; - } - - /** - * Set the object id. For Hibernate. - * @param id The id to set. - */ - protected void setId(long id) - { - fID = id; - } - - /** - * Get the id of this node. - * @return The object id. - */ - public long getId() - { - return fID; - } - - /** - * Set the versionID for this node. - * @param versionID The id to set. - */ - public void setVersionID(int versionID) - { - fVersionID = versionID; - } - - /** - * Get the version id of this node. - * @return The version id. - */ - public int getVersionID() - { - return fVersionID; - } - - /** - * Set the basic attributes. For Hibernate. - * @param attrs - */ - protected void setBasicAttributes(BasicAttributes attrs) - { - fBasicAttributes = attrs; - } - - /** - * Get the basic attributes. - * @return The basic attributes. - */ - public BasicAttributes getBasicAttributes() - { - return fBasicAttributes; - } - - /** - * Get whether this is a new node. - * @return Whether this is new. - */ - public boolean getIsNew() - { - return fStoreNew != null; - } - - /** - * Set the version for concurrency control - * @param vers - */ - protected void setVers(long vers) - { - fVers = vers; - } - - /** - * Get the version for concurrency control. - * @return The version for optimistic locks. - */ - protected long getVers() - { - return fVers; - } - - /** - * Get whether this is a root node. - * @return Whether this is a root node. - */ - public boolean getIsRoot() - { - return fIsRoot; - } - - /** - * @param isRoot - */ - public void setIsRoot(boolean isRoot) - { - fIsRoot = isRoot; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.avm.AVMNode#updateModTime() - */ - public void updateModTime() - { - if (DEBUG) - { - checkReadOnly(); - } - String user = - RawServices.Instance().getAuthenticationComponent().getCurrentUserName(); - if (user == null) - { - user = RawServices.Instance().getAuthenticationComponent().getSystemUserName(); - } - fBasicAttributes.setModDate(System.currentTimeMillis()); - fBasicAttributes.setLastModifier(user); - } - - /** - * Copy all properties from another node. - * @param other The other node. - */ - protected void copyProperties(AVMNode other) - { - fProperties = new HashMap(); - for (Map.Entry entry : other.getProperties().entrySet()) - { - fProperties.put(entry.getKey(), entry.getValue()); - } - } - - /** - * Copy all aspects from another node. - * @param other The other node. - */ - protected void copyAspects(AVMNode other) - { - fAspects = new HashSet(other.getAspects()); - } - - protected void copyCreationAndOwnerBasicAttributes(AVMNode other) - { - fBasicAttributes.setCreateDate(other.getBasicAttributes().getCreateDate()); - fBasicAttributes.setCreator(other.getBasicAttributes().getCreator()); - fBasicAttributes.setOwner(other.getBasicAttributes().getOwner()); - } - - protected void copyACLs(AVMNode other, Long parentAcl, ACLCopyMode mode) - { - DbAccessControlList acl = other.getAcl(); - if (acl != null) - { - setAcl(acl.getCopy(parentAcl, mode)); - } - } - - /** - * Copy out metadata from another node. - * @param other The other node. - */ - public void copyMetaDataFrom(AVMNode other, Long parentAcl) - { - copyAspects(other); - copyACLs(other, parentAcl, ACLCopyMode.COPY); - copyProperties(other); - copyCreationAndOwnerBasicAttributes(other); - } - - /** - * Set a property on a node. Overwrite it if it exists. - * @param name The name of the property. - * @param value The value to set. - */ - public void setProperty(Long qnameEntityId, PropertyValue value) - { - if (DEBUG) - { - checkReadOnly(); - } - fProperties.put(qnameEntityId, value); - } - - public void addProperties(Map properties) - { - for (Map.Entry entry : properties.entrySet()) - { - fProperties.put(entry.getKey(), entry.getValue()); - } - } - - /** - * Set a collection of properties on this node. - * @param properties The Map of QNames to PropertyValues. - */ - public void setProperties(Map properties) - { - fProperties = properties; - } - - /** - * Get a property by name. - * @param name The name of the property. - * @return The PropertyValue or null if non-existent. - */ - public PropertyValue getProperty(Long qnameEntityId) - { - return fProperties.get(qnameEntityId); - } - - /** - * {@inheritDoc} - */ - public Map getProperties() - { - return fProperties; - } - - /** - * Delete a property from this node. - * @param name The name of the property. - */ - public void deleteProperty(Long qnameEntityId) - { - if (DEBUG) - { - checkReadOnly(); - } - fProperties.remove(qnameEntityId); - } - - /** - * Delete all properties from this node. - */ - public void deleteProperties() - { - fProperties.clear(); - } - - /** - * Set the ACL on this node. - * @param acl The ACL to set. - */ - public void setAcl(DbAccessControlList acl) - { - fACL = acl; - } - - /** - * Get the ACL on this node. - * @return The ACL on this node. - */ - public DbAccessControlList getAcl() - { - return fACL; - } - - /** - * Set the store we are new in. - * @param store The store we are new in. - */ - public void setStoreNew(AVMStore store) - { - fStoreNew = store; - } - - /** - * Get the possibly null store we are new in. - * @return The store we are new in. - */ - public AVMStore getStoreNew() - { - return fStoreNew; - } - - protected void checkReadOnly() - { - if (getStoreNew() == null) - { - throw new AVMReadOnlyException("Write Operation on R/O Node."); - } - } - - /* (non-Javadoc) - * @see org.alfresco.repo.avm.AVMNode#getGuid() - */ - public String getGuid() - { - return fGUID; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.avm.AVMNode#setGuid(java.lang.String) - */ - public void setGuid(String guid) - { - fGUID = guid; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.avm.AVMNode#getAspects() - */ - public Set getAspects() - { - return fAspects; - } - - /** - * Set the aspects on this node. - * @param aspects - */ - public void setAspects(Set aspects) - { - fAspects = aspects; - } -} +/* + * Copyright (C) 2005-2009 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" */ + +package org.alfresco.repo.avm; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.avm.util.RawServices; +import org.alfresco.repo.domain.DbAccessControlList; +import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.security.permissions.ACLCopyMode; +import org.alfresco.service.cmr.avm.AVMReadOnlyException; +import org.alfresco.util.GUID; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Base class for all repository file system like objects. + * @author britt + */ +public abstract class AVMNodeImpl implements AVMNode, Serializable +{ + private static Log fgLogger = LogFactory.getLog(AVMNodeImpl.class); + + protected static final boolean DEBUG = fgLogger.isDebugEnabled(); + + /** + * The Object ID. + */ + private long fID; + + /** + * The Version ID. + */ + private int fVersionID; + + /** + * The basic attributes of this. Owner, creator, mod time, etc. + */ + private BasicAttributes fBasicAttributes; + + /** + * The version number (for concurrency control). + */ + private long fVers; + + /** + * The rootness of this node. + */ + private boolean fIsRoot; + + /** + * The ACL on this node. + */ + private DbAccessControlList fACL; + + /** + * The Store that we're new in. + */ + private AVMStore fStoreNew; + + /** + * The GUID for this version. + */ + private String fGUID; + + /** + * The Aspects that belong to this node. + */ + private Set fAspects; + + private Map fProperties; + + /** + * Default constructor. + */ + protected AVMNodeImpl() + { + fAspects = new HashSet(); + fProperties = new HashMap(); + } + + /** + * Constructor used when creating a new concrete subclass instance. + * @param store The AVMStore that owns this. + */ + protected AVMNodeImpl(AVMStore store) + { + fAspects = new HashSet(); + fProperties = new HashMap(); + fVersionID = -1; + fIsRoot = false; + long time = System.currentTimeMillis(); + String user = + RawServices.Instance().getAuthenticationComponent().getCurrentUserName(); + if (user == null) + { + user = RawServices.Instance().getAuthenticationComponent().getSystemUserName(); + } + fBasicAttributes = new BasicAttributesImpl(user, + user, + user, + time, + time, + time); + fStoreNew = store; + fGUID = GUID.generate(); + } + + /** + * Set the ancestor of this node. + * @param ancestor The ancestor to set. + */ + public void setAncestor(AVMNode ancestor) + { + if (ancestor == null) + { + return; + } + HistoryLinkImpl link = new HistoryLinkImpl(); + link.setAncestor(ancestor); + link.setDescendent(this); + AVMDAOs.Instance().fHistoryLinkDAO.save(link); + } + + /** + * Change the ancestor of this node. + * @param ancestor The new ancestor to give it. + */ + public void changeAncestor(AVMNode ancestor) + { + HistoryLink old = AVMDAOs.Instance().fHistoryLinkDAO.getByDescendent(this); + if (old != null) + { + AVMDAOs.Instance().fHistoryLinkDAO.delete(old); + } + setAncestor(ancestor); + } + + /** + * Get the ancestor of this node. + * @return The ancestor of this node. + */ + public AVMNode getAncestor() + { + return AVMDAOs.Instance().fAVMNodeDAO.getAncestor(this); + } + + /** + * Set the node that was merged into this. + * @param mergedFrom The node that was merged into this. + */ + public void setMergedFrom(AVMNode mergedFrom) + { + if (mergedFrom == null) + { + return; + } + MergeLinkImpl link = new MergeLinkImpl(); + link.setMfrom(mergedFrom); + link.setMto(this); + AVMDAOs.Instance().fMergeLinkDAO.save(link); + } + + /** + * Get the node that was merged into this. + * @return The node that was merged into this. + */ + public AVMNode getMergedFrom() + { + return AVMDAOs.Instance().fAVMNodeDAO.getMergedFrom(this); + } + + /** + * Equality based on object ids. + * @param obj The thing to compare against. + * @return Equality. + */ + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof AVMNode)) + { + return false; + } + return fID == ((AVMNode)obj).getId(); + } + + /** + * Get a reasonable hash value. + * @return The hash code. + */ + @Override + public int hashCode() + { + return (int)fID; + } + + /** + * Set the object id. For Hibernate. + * @param id The id to set. + */ + protected void setId(long id) + { + fID = id; + } + + /** + * Get the id of this node. + * @return The object id. + */ + public long getId() + { + return fID; + } + + /** + * Set the versionID for this node. + * @param versionID The id to set. + */ + public void setVersionID(int versionID) + { + fVersionID = versionID; + } + + /** + * Get the version id of this node. + * @return The version id. + */ + public int getVersionID() + { + return fVersionID; + } + + /** + * Set the basic attributes. For Hibernate. + * @param attrs + */ + protected void setBasicAttributes(BasicAttributes attrs) + { + fBasicAttributes = attrs; + } + + /** + * Get the basic attributes. + * @return The basic attributes. + */ + public BasicAttributes getBasicAttributes() + { + return fBasicAttributes; + } + + /** + * Get whether this is a new node. + * @return Whether this is new. + */ + public boolean getIsNew() + { + return fStoreNew != null; + } + + /** + * Set the version for concurrency control + * @param vers + */ + protected void setVers(long vers) + { + fVers = vers; + } + + /** + * Get the version for concurrency control. + * @return The version for optimistic locks. + */ + protected long getVers() + { + return fVers; + } + + /** + * Get whether this is a root node. + * @return Whether this is a root node. + */ + public boolean getIsRoot() + { + return fIsRoot; + } + + /** + * @param isRoot + */ + public void setIsRoot(boolean isRoot) + { + fIsRoot = isRoot; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.avm.AVMNode#updateModTime() + */ + public void updateModTime() + { + if (DEBUG) + { + checkReadOnly(); + } + String user = + RawServices.Instance().getAuthenticationComponent().getCurrentUserName(); + if (user == null) + { + user = RawServices.Instance().getAuthenticationComponent().getSystemUserName(); + } + fBasicAttributes.setModDate(System.currentTimeMillis()); + fBasicAttributes.setLastModifier(user); + } + + /** + * Copy all properties from another node. + * @param other The other node. + */ + protected void copyProperties(AVMNode other) + { + fProperties = new HashMap(); + for (Map.Entry entry : other.getProperties().entrySet()) + { + fProperties.put(entry.getKey(), entry.getValue()); + } + } + + /** + * Copy all aspects from another node. + * @param other The other node. + */ + protected void copyAspects(AVMNode other) + { + fAspects = new HashSet(other.getAspects()); + } + + protected void copyCreationAndOwnerBasicAttributes(AVMNode other) + { + fBasicAttributes.setCreateDate(other.getBasicAttributes().getCreateDate()); + fBasicAttributes.setCreator(other.getBasicAttributes().getCreator()); + fBasicAttributes.setOwner(other.getBasicAttributes().getOwner()); + } + + protected void copyACLs(AVMNode other, Long parentAcl, ACLCopyMode mode) + { + DbAccessControlList acl = other.getAcl(); + if (acl != null) + { + setAcl(acl.getCopy(parentAcl, mode)); + } + } + + /** + * Copy out metadata from another node. + * @param other The other node. + */ + public void copyMetaDataFrom(AVMNode other, Long parentAcl) + { + copyAspects(other); + copyACLs(other, parentAcl, ACLCopyMode.COPY); + copyProperties(other); + copyCreationAndOwnerBasicAttributes(other); + } + + /** + * Set a property on a node. Overwrite it if it exists. + * @param name The name of the property. + * @param value The value to set. + */ + public void setProperty(Long qnameEntityId, PropertyValue value) + { + if (DEBUG) + { + checkReadOnly(); + } + fProperties.put(qnameEntityId, value); + } + + public void addProperties(Map properties) + { + for (Map.Entry entry : properties.entrySet()) + { + fProperties.put(entry.getKey(), entry.getValue()); + } + } + + /** + * Set a collection of properties on this node. + * @param properties The Map of QNames to PropertyValues. + */ + public void setProperties(Map properties) + { + fProperties = properties; + } + + /** + * Get a property by name. + * @param name The name of the property. + * @return The PropertyValue or null if non-existent. + */ + public PropertyValue getProperty(Long qnameEntityId) + { + return fProperties.get(qnameEntityId); + } + + /** + * {@inheritDoc} + */ + public Map getProperties() + { + return fProperties; + } + + /** + * Delete a property from this node. + * @param name The name of the property. + */ + public void deleteProperty(Long qnameEntityId) + { + if (DEBUG) + { + checkReadOnly(); + } + fProperties.remove(qnameEntityId); + } + + /** + * Delete all properties from this node. + */ + public void deleteProperties() + { + fProperties.clear(); + } + + /** + * Set the ACL on this node. + * @param acl The ACL to set. + */ + public void setAcl(DbAccessControlList acl) + { + fACL = acl; + } + + /** + * Get the ACL on this node. + * @return The ACL on this node. + */ + public DbAccessControlList getAcl() + { + return fACL; + } + + /** + * Set the store we are new in. + * @param store The store we are new in. + */ + public void setStoreNew(AVMStore store) + { + fStoreNew = store; + } + + /** + * Get the possibly null store we are new in. + * @return The store we are new in. + */ + public AVMStore getStoreNew() + { + return fStoreNew; + } + + protected void checkReadOnly() + { + if (getStoreNew() == null) + { + throw new AVMReadOnlyException("Write Operation on R/O Node."); + } + } + + /* (non-Javadoc) + * @see org.alfresco.repo.avm.AVMNode#getGuid() + */ + public String getGuid() + { + return fGUID; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.avm.AVMNode#setGuid(java.lang.String) + */ + public void setGuid(String guid) + { + fGUID = guid; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.avm.AVMNode#getAspects() + */ + public Set getAspects() + { + return fAspects; + } + + /** + * Set the aspects on this node. + * @param aspects + */ + public void setAspects(Set aspects) + { + fAspects = aspects; + } +} diff --git a/source/java/org/alfresco/repo/avm/AVMRepository.java b/source/java/org/alfresco/repo/avm/AVMRepository.java index 705a048eba..6d9b0708a7 100644 --- a/source/java/org/alfresco/repo/avm/AVMRepository.java +++ b/source/java/org/alfresco/repo/avm/AVMRepository.java @@ -1,3371 +1,3320 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" */ - -package org.alfresco.repo.avm; - -import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; - -import org.alfresco.model.WCMModel; -import org.alfresco.repo.content.ContentStore; -import org.alfresco.repo.domain.DbAccessControlList; -import org.alfresco.repo.domain.PropertyValue; -import org.alfresco.repo.domain.QNameDAO; -import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor.StoreType; -import org.alfresco.repo.security.permissions.ACLCopyMode; -import org.alfresco.repo.security.permissions.AccessDeniedException; -import org.alfresco.repo.transaction.AlfrescoTransactionSupport; -import org.alfresco.service.cmr.avm.AVMBadArgumentException; -import org.alfresco.service.cmr.avm.AVMCycleException; -import org.alfresco.service.cmr.avm.AVMException; -import org.alfresco.service.cmr.avm.AVMExistsException; -import org.alfresco.service.cmr.avm.AVMNodeDescriptor; -import org.alfresco.service.cmr.avm.AVMNotFoundException; -import org.alfresco.service.cmr.avm.AVMStoreDescriptor; -import org.alfresco.service.cmr.avm.AVMWrongTypeException; -import org.alfresco.service.cmr.avm.LayeringDescriptor; -import org.alfresco.service.cmr.avm.VersionDescriptor; -import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.PermissionContext; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.Pair; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * This or AVMStore are the implementors of the operations specified by AVMService. - * - * @author britt - */ -public class AVMRepository -{ - @SuppressWarnings("unused") - private static Log fgLogger = LogFactory.getLog(AVMRepository.class); - - /** - * The single instance of AVMRepository. - */ - private static AVMRepository fgInstance; - - /** - * The current lookup count. - */ - private ThreadLocal fLookupCount; - - /** - * The node id issuer. - */ - private Issuer fNodeIssuer; - - /** - * The layer id issuer. - */ - private Issuer fLayerIssuer; - - /** - * Reference to the ContentStoreImpl - */ - private ContentStore fContentStore; - - /** - * The Lookup Cache instance. - */ - private LookupCache fLookupCache; - - private QNameDAO qnameDAO; - - private AVMStoreDAO fAVMStoreDAO; - - private AVMNodeDAO fAVMNodeDAO; - - private VersionRootDAO fVersionRootDAO; - - private VersionLayeredNodeEntryDAO fVersionLayeredNodeEntryDAO; - - private AVMStorePropertyDAO fAVMStorePropertyDAO; - - private ChildEntryDAO fChildEntryDAO; - - private PermissionService fPermissionService; - - private DictionaryService fDictionaryService; - - // A bunch of TransactionListeners that do work for this. - - /** - * One for create store. - */ - private CreateStoreTxnListener fCreateStoreTxnListener; - - /** - * One for purge store. - */ - private PurgeStoreTxnListener fPurgeStoreTxnListener; - - /** - * One for create version. - */ - private CreateVersionTxnListener fCreateVersionTxnListener; - - /** - * One for purge version. - */ - private PurgeVersionTxnListener fPurgeVersionTxnListener; - - /** - * Create a new one. - */ - public AVMRepository() - { - fLookupCount = new ThreadLocal(); - fgInstance = this; - } - - /** - * Set the node issuer. For Spring. - * - * @param nodeIssuer - * The issuer. - */ - public void setNodeIssuer(Issuer nodeIssuer) - { - fNodeIssuer = nodeIssuer; - } - - /** - * Set the layer issuer. For Spring. - * - * @param layerIssuer - * The issuer. - */ - public void setLayerIssuer(Issuer layerIssuer) - { - fLayerIssuer = layerIssuer; - } - - /** - * Set the ContentService. - */ - public void setContentStore(ContentStore store) - { - fContentStore = store; - } - - /** - * Set the Lookup Cache instance. - * - * @param cache - * The instance to set. - */ - public void setLookupCache(LookupCache cache) - { - fLookupCache = cache; - } - - public void setCreateStoreTxnListener(CreateStoreTxnListener listener) - { - fCreateStoreTxnListener = listener; - } - - public void setPurgeStoreTxnListener(PurgeStoreTxnListener listener) - { - fPurgeStoreTxnListener = listener; - } - - public void setCreateVersionTxnListener(CreateVersionTxnListener listener) - { - fCreateVersionTxnListener = listener; - } - - public void setPurgeVersionTxnListener(PurgeVersionTxnListener listener) - { - fPurgeVersionTxnListener = listener; - } - - public void setQnameDAO(QNameDAO qnameDAO) - { - this.qnameDAO = qnameDAO; - } - - public void setAvmStoreDAO(AVMStoreDAO dao) - { - fAVMStoreDAO = dao; - } - - public void setAvmNodeDAO(AVMNodeDAO dao) - { - fAVMNodeDAO = dao; - } - - public void setVersionRootDAO(VersionRootDAO dao) - { - fVersionRootDAO = dao; - } - - public void setVersionLayeredNodeEntryDAO(VersionLayeredNodeEntryDAO dao) - { - fVersionLayeredNodeEntryDAO = dao; - } - - public void setAvmStorePropertyDAO(AVMStorePropertyDAO dao) - { - fAVMStorePropertyDAO = dao; - } - - public void setChildEntryDAO(ChildEntryDAO dao) - { - fChildEntryDAO = dao; - } - - public void setPermissionService(PermissionService service) - { - fPermissionService = service; - } - - public void setDictionaryService(DictionaryService service) - { - fDictionaryService = service; - } - - /** - * Create a file. - * - * @param path - * The path to the containing directory. - * @param name - * The name for the new file. - */ - public OutputStream createFile(String path, String name) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - OutputStream out = store.createFile(pathParts[1], name); - return out; - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Create a file with the given File as content. - * - * @param path - * The path to the containing directory. - * @param name - * The name to give the file. - * @param data - * The file contents. - */ - public void createFile(String path, String name, File data, List aspects, Map properties) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.createFile(pathParts[1], name, data, aspects, properties); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Create a new directory. - * - * @param path - * The path to the containing directory. - * @param name - * The name to give the directory. - */ - public void createDirectory(String path, String name, List aspects, Map properties) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.createDirectory(pathParts[1], name, aspects, properties); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Create a new directory. This assumes that the parent is already copied and therefore should only be used with - * great care. - * - * @param parent - * The parent node. - * @param name - * The name of the new directory. - * @return A descriptor for the newly created directory. - */ - public AVMNodeDescriptor createDirectory(AVMNodeDescriptor parent, String name) - { - AVMNode node = fAVMNodeDAO.getByID(parent.getId()); - if (node == null) - { - throw new AVMNotFoundException(parent.getId() + " not found."); - } - if (!(node instanceof DirectoryNode)) - { - throw new AVMWrongTypeException("Not a directory."); - } - if (!can(null, node, PermissionService.CREATE_CHILDREN, true)) - { - throw new AccessDeniedException("Not allowed to write in: " + parent); - } - // We need the store to do anything so... - String[] pathParts = SplitPath(parent.getPath()); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - DirectoryNode dir = (DirectoryNode) node; - DirectoryNode child = null; - Long parentAcl = dir.getAcl() == null ? null : dir.getAcl().getId(); - if (dir instanceof LayeredDirectoryNode) - { - child = new LayeredDirectoryNodeImpl((String) null, store, null, parentAcl, ACLCopyMode.INHERIT); - ((LayeredDirectoryNode) child).setPrimaryIndirection(false); - ((LayeredDirectoryNode) child).setLayerID(parent.getLayerID()); - } - else - { - child = new PlainDirectoryNodeImpl(store); - } - dir.putChild(name, child); - DbAccessControlList acl = dir.getAcl(); - child.setAcl(acl != null ? acl.getCopy(acl.getId(), ACLCopyMode.INHERIT) : null); - fLookupCache.onWrite(pathParts[0]); - AVMNodeDescriptor desc = child.getDescriptor(parent.getPath(), name, parent.getIndirection(), parent.getIndirectionVersion()); - return desc; - } - - /** - * Create a new layered directory. - * - * @param srcPath - * The target indirection for the new layered directory. - * @param dstPath - * The path to the containing directory. - * @param name - * The name for the new directory. - */ - public void createLayeredDirectory(String srcPath, String dstPath, String name) - { - if (dstPath.indexOf(srcPath) == 0) - { - throw new AVMCycleException("Cycle would be created."); - } - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(dstPath); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.createLayeredDirectory(srcPath, pathParts[1], name); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Create a new layered file. - * - * @param srcPath - * The target indirection for the new layered file. - * @param dstPath - * The path to the containing directory. - * @param name - * The name of the new layered file. - */ - public void createLayeredFile(String srcPath, String dstPath, String name) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(dstPath); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.createLayeredFile(srcPath, pathParts[1], name); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Create a new AVMStore. - * - * @param name - * The name to give the new AVMStore. - */ - public void createAVMStore(String name) - { - AlfrescoTransactionSupport.bindListener(fCreateStoreTxnListener); - if (getAVMStoreByName(name) != null) - { - throw new AVMExistsException("AVMStore exists: " + name); - } - // Newing up the object causes it to be written to the db. - @SuppressWarnings("unused") - AVMStore rep = new AVMStoreImpl(this, name); - // Special handling for AVMStore creation. - rep.getRoot().setStoreNew(null); - fCreateStoreTxnListener.storeCreated(name); - } - - /** - * Create a new branch. - * - * @param version - * The version to branch off. - * @param srcPath - * The path to make a branch from. - * @param dstPath - * The containing directory. - * @param name - * The name of the new branch. - */ - public void createBranch(int version, String srcPath, String dstPath, String name) - { - if (dstPath.indexOf(srcPath) == 0) - { - throw new AVMCycleException("Cycle would be created."); - } - // Lookup the src node. - fLookupCount.set(1); - String[] pathParts; - Lookup sPath; - List layeredEntries = null; - try - { - pathParts = SplitPath(srcPath); - AVMStore srcRepo = getAVMStoreByName(pathParts[0]); - if (srcRepo == null) - { - throw new AVMNotFoundException("Store not found."); - } - if (version < 0) - { - fLookupCache.onSnapshot(pathParts[0]); - version = srcRepo.createSnapshot("Branch Snapshot", null, new HashMap()).get(pathParts[0]); - } - sPath = srcRepo.lookup(version, pathParts[1], false, false); - if (sPath == null) - { - throw new AVMNotFoundException("Path not found."); - } - VersionRoot lastVersion = fVersionRootDAO.getByVersionID(srcRepo, version); - layeredEntries = fVersionLayeredNodeEntryDAO.get(lastVersion); - } - finally - { - fLookupCount.set(null); - } - // Lookup the destination directory. - fLookupCount.set(1); - try - { - pathParts = SplitPath(dstPath); - AVMStore dstRepo = getAVMStoreByName(pathParts[0]); - if (dstRepo == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1], true); - if (dPath == null) - { - throw new AVMNotFoundException("Path not found."); - } - DirectoryNode dirNode = (DirectoryNode) dPath.getCurrentNode(); - if (!can(dstRepo, dirNode, PermissionService.ADD_CHILDREN, dPath.getDirectlyContained())) - { - throw new AccessDeniedException("Not permitted to add children: " + dstPath); - } - AVMNode srcNode = sPath.getCurrentNode(); - AVMNode dstNode = null; - // We do different things depending on what kind of thing we're - // branching from. I'd be considerably happier if we disallowed - // certain scenarios, but Jon won't let me :P (bhp). - - Long inheritAcl = srcNode.getAcl() == null ? null : srcNode.getAcl().getId(); - - if (srcNode.getType() == AVMNodeType.PLAIN_DIRECTORY) - { - dstNode = new PlainDirectoryNodeImpl((PlainDirectoryNode) srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); - } - else if (srcNode.getType() == AVMNodeType.LAYERED_DIRECTORY) - { - dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, sPath, false, inheritAcl, ACLCopyMode.INHERIT); - ((LayeredDirectoryNode) dstNode).setLayerID(issueLayerID()); - } - else if (srcNode.getType() == AVMNodeType.LAYERED_FILE) - { - dstNode = new LayeredFileNodeImpl((LayeredFileNode) srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); - } - else - // This is a plain file. - { - dstNode = new PlainFileNodeImpl((PlainFileNode) srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); - } - // dstNode.setVersionID(dstRepo.getNextVersionID()); - dstNode.setAncestor(srcNode); - dirNode.putChild(name, dstNode); - // dirNode.updateModTime(); - String beginingPath = AVMNodeConverter.NormalizePath(srcPath); - String finalPath = AVMNodeConverter.ExtendAVMPath(dstPath, name); - finalPath = AVMNodeConverter.NormalizePath(finalPath); - VersionRoot latestVersion = fVersionRootDAO.getMaxVersion(dstRepo); - for (VersionLayeredNodeEntry entry : layeredEntries) - { - String path = entry.getPath(); - if (!path.startsWith(srcPath)) - { - continue; - } - String newPath = finalPath + path.substring(beginingPath.length()); - VersionLayeredNodeEntry newEntry = new VersionLayeredNodeEntryImpl(latestVersion, newPath); - fVersionLayeredNodeEntryDAO.save(newEntry); - } - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get an output stream to a file. - * - * @param path - * The full path to the file. - * @return An OutputStream. - */ - public OutputStream getOutputStream(String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - OutputStream out = store.getOutputStream(pathParts[1]); - return out; - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get a content reader from a file node. - * - * @param version - * The version of the file. - * @param path - * The path to the file. - * @return A ContentReader. - */ - public ContentReader getContentReader(int version, String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found: " + pathParts[0]); - } - return store.getContentReader(version, pathParts[1]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get a ContentWriter to a file node. - * - * @param path - * The path to the file. - * @return A ContentWriter. - */ - public ContentWriter createContentWriter(String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found: " + pathParts[0]); - } - fLookupCache.onWrite(pathParts[0]); - ContentWriter writer = store.createContentWriter(pathParts[1]); - return writer; - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Rename a node. - * - * @param srcPath - * Source containing directory. - * @param srcName - * Source name. - * @param dstPath - * Destination containing directory. - * @param dstName - * Destination name. - */ - public void rename(String srcPath, String srcName, String dstPath, String dstName) - { - // This is about as ugly as it gets. - if ((dstPath + "/").indexOf(srcPath + srcName + "/") == 0) - { - throw new AVMCycleException("Cyclic rename."); - } - fLookupCount.set(1); - String[] pathParts; - Lookup sPath; - DirectoryNode srcDir; - AVMNode srcNode; - try - { - pathParts = SplitPath(srcPath); - AVMStore srcRepo = getAVMStoreByName(pathParts[0]); - if (srcRepo == null) - { - throw new AVMNotFoundException("Store not found."); - } - sPath = srcRepo.lookupDirectory(-1, pathParts[1], true); - if (sPath == null) - { - throw new AVMNotFoundException("Path not found."); - } - srcDir = (DirectoryNode) sPath.getCurrentNode(); - - Pair temp = srcDir.lookupChild(sPath, srcName, false); - srcNode = (temp == null) ? null : temp.getFirst(); - if (srcNode == null) - { - throw new AVMNotFoundException("Not found: " + srcName); - } - if (!can(srcRepo, srcNode, PermissionService.DELETE_NODE, false)) - { - throw new AccessDeniedException("Not allowed to delete target: " + srcPath); - } - - fLookupCache.onDelete(pathParts[0]); - } - finally - { - fLookupCount.set(null); - } - fLookupCount.set(1); - try - { - pathParts = SplitPath(dstPath); - AVMStore dstRepo = getAVMStoreByName(pathParts[0]); - if (dstRepo == null) - { - throw new AVMNotFoundException("Store not found."); - } - Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1], true); - if (dPath == null) - { - throw new AVMNotFoundException("Path not found."); - } - DirectoryNode dstDir = (DirectoryNode) dPath.getCurrentNode(); - if (!can(dstRepo, dstDir, PermissionService.ADD_CHILDREN, dPath.getDirectlyContained())) - { - throw new AccessDeniedException("Not allowed to write: " + dstPath); - } - Pair temp = dstDir.lookupChild(dPath, dstName, true); - AVMNode child = (temp == null) ? null : temp.getFirst(); - if (child != null && child.getType() != AVMNodeType.DELETED_NODE) - { - throw new AVMExistsException("Node exists: " + dstName); - } - - Long parentAcl = dstDir.getAcl() == null ? null : dstDir.getAcl().getId(); - - AVMNode dstNode = null; - // We've passed the check, so we can go ahead and do the rename. - if (srcNode.getType() == AVMNodeType.PLAIN_DIRECTORY) - { - // If the source is layered then the renamed thing needs to be layered also. - if (sPath.isLayered()) - { - // If this is a rename happening in the same layer we make a new - // OverlayedDirectoryNode that is not a primary indirection layer. - // Otherwise we do make the new OverlayedDirectoryNode a primary - // Indirection layer. This complexity begs the question of whether - // we should allow renames from within one layer to within another - // layer. Allowing it makes the logic absurdly complex. - if (dPath.isLayered() && dPath.getTopLayer().equals(sPath.getTopLayer())) - { - dstNode = new LayeredDirectoryNodeImpl((PlainDirectoryNode) srcNode, dstRepo, sPath, true, parentAcl, ACLCopyMode.COPY); - ((LayeredDirectoryNode) dstNode).setLayerID(sPath.getTopLayer().getLayerID()); - } - else - { - dstNode = new LayeredDirectoryNodeImpl((DirectoryNode) srcNode, dstRepo, sPath, srcName, parentAcl, ACLCopyMode.COPY); - ((LayeredDirectoryNode) dstNode).setLayerID(issueLayerID()); - } - } - else - { - dstNode = new PlainDirectoryNodeImpl((PlainDirectoryNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); - } - } - else if (srcNode.getType() == AVMNodeType.LAYERED_DIRECTORY) - { - if (!sPath.isLayered() || (sPath.isInThisLayer() && srcDir.getType() == AVMNodeType.LAYERED_DIRECTORY && ((LayeredDirectoryNode) srcDir).directlyContains(srcNode))) - { - Lookup srcLookup = lookup(-1, srcPath + "/" + srcName, true); - // Use the simple 'copy' constructor. - dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, srcLookup, true, parentAcl, ACLCopyMode.COPY); - ((LayeredDirectoryNode) dstNode).setLayerID(((LayeredDirectoryNode) srcNode).getLayerID()); - } - else - { - // If the source node is a primary indirection, then the 'copy' constructor - // is used. Otherwise the alternate constructor is called and its - // indirection is calculated from it's source context. - if (((LayeredDirectoryNode) srcNode).getPrimaryIndirection()) - { - Lookup srcLookup = lookup(-1, srcPath + "/" + srcName, true); - dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, srcLookup, true, parentAcl, ACLCopyMode.COPY); - } - else - { - dstNode = new LayeredDirectoryNodeImpl((DirectoryNode) srcNode, dstRepo, sPath, srcName, parentAcl, ACLCopyMode.COPY); - } - // What needs to be done here is dependent on whether the - // rename is to a layered context. If so then it should get the layer id - // of its destination parent. Otherwise it should get a new layer - // id. - if (dPath.isLayered()) - { - ((LayeredDirectoryNode) dstNode).setLayerID(dPath.getTopLayer().getLayerID()); - } - else - { - ((LayeredDirectoryNode) dstNode).setLayerID(issueLayerID()); - } - } - } - else if (srcNode.getType() == AVMNodeType.LAYERED_FILE) - { - dstNode = new LayeredFileNodeImpl((LayeredFileNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); - } - else - // This is a plain file node. - { - dstNode = new PlainFileNodeImpl((PlainFileNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); - } - srcDir.removeChild(sPath, srcName); - // srcDir.updateModTime(); - // dstNode.setVersionID(dstRepo.getNextVersionID()); - if (child != null) - { - dstNode.setAncestor(child); - } - //dstDir.updateModTime(); - dstDir.putChild(dstName, dstNode); - if (child == null) - { - dstNode.setAncestor(srcNode); - } - fLookupCache.onWrite(pathParts[0]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Uncover a deleted name in a layered directory. - * - * @param dirPath - * The path to the layered directory. - * @param name - * The name to uncover. - */ - public void uncover(String dirPath, String name) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(dirPath); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.uncover(pathParts[1], name); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Create a snapshot of a single AVMStore. - * - * @param store - * The name of the repository. - * @param tag - * The short description. - * @param description - * The thick description. - * @return The version id of the newly snapshotted repository. - */ - public Map createSnapshot(String storeName, String tag, String description) - { - try - { - fAVMNodeDAO.noCache(); - AlfrescoTransactionSupport.bindListener(fCreateVersionTxnListener); - AVMStore store = getAVMStoreByName(storeName); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - Map result = store.createSnapshot(tag, description, new HashMap()); - for (Map.Entry entry : result.entrySet()) - { - fLookupCache.onSnapshot(entry.getKey()); - fCreateVersionTxnListener.versionCreated(entry.getKey(), entry.getValue()); - } - return result; - } - finally - { - fAVMNodeDAO.yesCache(); - } - } - - /** - * Remove a node and everything underneath it. - * - * @param path - * The path to the containing directory. - * @param name - * The name of the node to remove. - */ - public void remove(String path, String name) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onDelete(pathParts[0]); - store.removeNode(pathParts[1], name); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get rid of all content that lives only in the given AVMStore. Also removes the AVMStore. - * - * @param name - * The name of the AVMStore to purge. - */ - @SuppressWarnings("unchecked") - public void purgeAVMStore(String name) - { - AlfrescoTransactionSupport.bindListener(fPurgeStoreTxnListener); - AVMStore store = getAVMStoreByName(name); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onDelete(name); - AVMNode root = store.getRoot(); - // TODO Probably a special PermissionService.PURGE is needed. - if (!can(store, root, PermissionService.DELETE_CHILDREN, true)) - { - throw new AccessDeniedException("Not allowed to purge: " + name); - } - root.setIsRoot(false); - List vRoots = fVersionRootDAO.getAllInAVMStore(store); - for (VersionRoot vr : vRoots) - { - AVMNode node = vr.getRoot(); - node.setIsRoot(false); - fVersionLayeredNodeEntryDAO.delete(vr); - fVersionRootDAO.delete(vr); - } - List newGuys = fAVMNodeDAO.getNewInStore(store); - for (AVMNode newGuy : newGuys) - { - newGuy.setStoreNew(null); - } - fAVMStorePropertyDAO.delete(store); - fAVMStoreDAO.delete(store); - fAVMStoreDAO.invalidateCache(); - fPurgeStoreTxnListener.storePurged(name); - } - - /** - * Remove all content specific to a AVMRepository and version. - * - * @param name - * The name of the AVMStore. - * @param version - * The version to purge. - */ - public void purgeVersion(String name, int version) - { - AlfrescoTransactionSupport.bindListener(fPurgeVersionTxnListener); - AVMStore store = getAVMStoreByName(name); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onDelete(name); - store.purgeVersion(version); - fPurgeVersionTxnListener.versionPurged(name, version); - } - - /** - * Get an input stream from a file. - * - * @param version - * The version to look under. - * @param path - * The path to the file. - * @return An InputStream. - */ - public InputStream getInputStream(int version, String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getInputStream(version, pathParts[1]); - } - finally - { - fLookupCount.set(null); - } - } - - public InputStream getInputStream(AVMNodeDescriptor desc) - { - AVMNode node = fAVMNodeDAO.getByID(desc.getId()); - if (!(node instanceof FileNode)) - { - throw new AVMWrongTypeException(desc + " is not a File."); - } - if (!can(null, node, PermissionService.READ_CONTENT, false)) - { - throw new AccessDeniedException("Not allowed to read content: " + desc); - } - FileNode file = (FileNode) node; - ContentData data = file.getContentData(null); - if (data == null) - { - throw new AVMException(desc + " has no content."); - } - ContentReader reader = fContentStore.getReader(data.getContentUrl()); - return reader.getContentInputStream(); - } - - /** - * Get a listing of a directory. - * - * @param version - * The version to look under. - * @param path - * The path to the directory. - * @param includeDeleted - * Whether to see DeletedNodes. - * @return A List of FolderEntries. - */ - public SortedMap getListing(int version, String path, boolean includeDeleted) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getListing(version, pathParts[1], includeDeleted); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get the list of nodes directly contained in a directory. - * - * @param version - * The version to look under. - * @param path - * The path to the directory to list. - * @return A Map of names to descriptors. - */ - public SortedMap getListingDirect(int version, String path, boolean includeDeleted) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getListingDirect(version, pathParts[1], includeDeleted); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get the list of nodes directly contained in a directory. - * - * @param dir - * The descriptor to the directory node. - * @param includeDeleted - * Whether to include deleted children. - * @return A Map of names to descriptors. - */ - public SortedMap getListingDirect(AVMNodeDescriptor dir, boolean includeDeleted) - { - AVMNode node = fAVMNodeDAO.getByID(dir.getId()); - if (node == null) - { - throw new AVMBadArgumentException("Invalid Node."); - } - if (!can(null, node, PermissionService.READ_CHILDREN, false)) - { - throw new AccessDeniedException("Not allowed to read children: " + dir); - } - if (node.getType() == AVMNodeType.PLAIN_DIRECTORY) - { - return getListing(dir, includeDeleted); - } - if (node.getType() != AVMNodeType.LAYERED_DIRECTORY) - { - throw new AVMWrongTypeException("Not a directory."); - } - LayeredDirectoryNode dirNode = (LayeredDirectoryNode) node; - return dirNode.getListingDirect(dir, includeDeleted); - } - - /** - * Get a directory listing from a directory node descriptor. - * - * @param dir - * The directory node descriptor. - * @return A SortedMap listing. - */ - public SortedMap getListing(AVMNodeDescriptor dir, boolean includeDeleted) - { - fLookupCount.set(1); - try - { - AVMNode node = fAVMNodeDAO.getByID(dir.getId()); - if (node == null) - { - throw new AVMBadArgumentException("Invalid Node."); - } - if (node.getType() != AVMNodeType.LAYERED_DIRECTORY && node.getType() != AVMNodeType.PLAIN_DIRECTORY) - { - throw new AVMWrongTypeException("Not a directory."); - } - if (!can(null, node, PermissionService.READ_CHILDREN, false)) - { - throw new AccessDeniedException("Not allowed to read children: " + dir); - } - DirectoryNode dirNode = (DirectoryNode) node; - SortedMap listing = dirNode.getListing(dir, includeDeleted); - return listing; - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get a directory listing from a directory node descriptor fo children that match the given pattern - * - * @param dir - * The directory node descriptor. - * @return A SortedMap listing. - */ - public SortedMap getListing(AVMNodeDescriptor dir, String childNamePattern, boolean includeDeleted) - { - fLookupCount.set(1); - try - { - AVMNode node = fAVMNodeDAO.getByID(dir.getId()); - if (node == null) - { - throw new AVMBadArgumentException("Invalid Node."); - } - if (node.getType() != AVMNodeType.LAYERED_DIRECTORY && node.getType() != AVMNodeType.PLAIN_DIRECTORY) - { - throw new AVMWrongTypeException("Not a directory."); - } - if (!can(null, node, PermissionService.READ_CHILDREN, false)) - { - throw new AccessDeniedException("Not allowed to read children: " + dir); - } - DirectoryNode dirNode = (DirectoryNode) node; - SortedMap listing = dirNode.getListing(dir, childNamePattern, includeDeleted); - return listing; - } - finally - { - fLookupCount.set(null); - } - } - - - /** - * Get the names of deleted nodes in a directory. - * - * @param version - * The version to look under. - * @param path - * The path to the directory. - * @return A List of names. - */ - public List getDeleted(int version, String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getDeleted(version, pathParts[1]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get descriptors of all AVMStores. - * - * @return A list of all descriptors. - */ - @SuppressWarnings("unchecked") - public List getAVMStores() - { - List l = fAVMStoreDAO.getAll(); - List result = new ArrayList(); - for (AVMStore store : l) - { - result.add(store.getDescriptor()); - } - return result; - } - - /** - * Get a descriptor for an AVMStore. - * - * @param name - * The name to get. - * @return The descriptor. - */ - public AVMStoreDescriptor getAVMStore(String name) - { - AVMStore store = getAVMStoreByName(name); - if (store == null) - { - return null; - } - return store.getDescriptor(); - } - - /** - * Get all version for a given AVMStore. - * - * @param name - * The name of the AVMStore. - * @return A Set will all the version ids. - */ - public List getAVMStoreVersions(String name) - { - AVMStore store = getAVMStoreByName(name); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getVersions(); - } - - /** - * Get the set of versions between (inclusive) of the given dates. From or to may be null but not both. - * - * @param name - * The name of the AVMRepository. - * @param from - * The earliest date. - * @param to - * The latest date. - * @return The Set of version IDs. - */ - public List getAVMStoreVersions(String name, Date from, Date to) - { - AVMStore store = getAVMStoreByName(name); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getVersions(from, to); - } - - /** - * Issue a node id. - * - * @return The new id. - */ - public long issueID() - { - return fNodeIssuer.issue(); - } - - /** - * Issue a new layer id. - * - * @return The new id. - */ - public long issueLayerID() - { - return fLayerIssuer.issue(); - } - - /** - * Get the indirection path for a layered node. - * - * @param version - * The version to look under. - * @param path - * The path to the node. - * @return The indirection path. - */ - public String getIndirectionPath(int version, String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getIndirectionPath(version, pathParts[1]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get the next version id for the given AVMStore. - * - * @param name - * The name of the AVMStore. - * @return The next version id. - */ - public int getLatestVersionID(String name) - { - AVMStore store = getAVMStoreByName(name); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getNextVersionID(); - } - - /** - * Get the latest extant snapshotted version id. - * - * @param name - * The store name. - */ - public int getLatestSnapshotID(String name) - { - AVMStore store = getAVMStoreByName(name); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getLastVersionID(); - } - - /** - * Get an AVMStore by name. - * - * @param name - * The name of the AVMStore. - * @return The AVMStore. - */ - private AVMStore getAVMStoreByName(String name) - { - AVMStore store = fAVMStoreDAO.getByName(name); - return store; - } - - /** - * Get a descriptor for an AVMStore root. - * - * @param version - * The version to get. - * @param name - * The name of the AVMStore. - * @return The descriptor for the root. - */ - public AVMNodeDescriptor getAVMStoreRoot(int version, String name) - { - AVMStore store = getAVMStoreByName(name); - if (store == null) - { - throw new AVMNotFoundException("Not found: " + name); - } - return store.getRoot(version); - } - - // TODO Fix this awful mess regarding cycle detection. - /** - * Lookup a node. - * - * @param version - * The version to look under. - * @param path - * The path to lookup. - * @param includeDeleted - * Whether to see DeletedNodes. - * @return A lookup object. - */ - public Lookup lookup(int version, String path, boolean includeDeleted) - { - Integer count = fLookupCount.get(); - try - { - if (count == null) - { - fLookupCount.set(1); - } - else - { - fLookupCount.set(count + 1); - } - if (fLookupCount.get() > 50) - { - throw new AVMCycleException("Cycle in lookup."); - } - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - return null; - } - return store.lookup(version, pathParts[1], false, includeDeleted); - } - finally - { - if (count == null) - { - fLookupCount.set(null); - } - } - } - - /** - * Lookup a descriptor from a directory descriptor. - * - * @param dir - * The directory descriptor. - * @param name - * The name of the child to lookup. - * @return The child's descriptor. - */ - public AVMNodeDescriptor lookup(AVMNodeDescriptor dir, String name, boolean includeDeleted) - { - fLookupCount.set(1); - try - { - AVMNode node = fAVMNodeDAO.getByID(dir.getId()); - if (node == null) - { - throw new AVMNotFoundException("Not found: " + dir.getId()); - } - if (node.getType() != AVMNodeType.LAYERED_DIRECTORY && node.getType() != AVMNodeType.PLAIN_DIRECTORY) - { - throw new AVMWrongTypeException("Not a directory."); - } - DirectoryNode dirNode = (DirectoryNode) node; - if (!can(null, dirNode, PermissionService.READ_CHILDREN, false)) - { - throw new AccessDeniedException("Not allowed to read children: " + dir); - } - return dirNode.lookupChild(dir, name, includeDeleted); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get all the paths to a particular node. - * - * @param desc - * The node descriptor. - * @return The list of version, paths. - */ - public List> getPaths(AVMNodeDescriptor desc) - { - AVMNode node = fAVMNodeDAO.getByID(desc.getId()); - if (node == null) - { - throw new AVMNotFoundException("Not found: " + desc); - } - List> paths = new ArrayList>(); - List components = new ArrayList(); - recursiveGetPaths(node, components, paths); - return paths; - } - - /** - * Get a single valid path for a node. - * - * @param desc - * The node descriptor. - * @return A version, path - */ - public Pair getAPath(AVMNodeDescriptor desc) - { - AVMNode node = fAVMNodeDAO.getByID(desc.getId()); - if (node == null) - { - throw new AVMNotFoundException("Could not find node: " + desc); - } - if (fgLogger.isDebugEnabled()) - { - fgLogger.debug("Getting A Path for: " + desc); - } - List components = new ArrayList(); - return recursiveGetAPath(node, components); - } - - /** - * Get all paths for a node reachable by HEAD. - * - * @param desc - * The node descriptor. - * @return A List of all the version, path Pairs that match. - */ - public List> getHeadPaths(AVMNodeDescriptor desc) - { - AVMNode node = fAVMNodeDAO.getByID(desc.getId()); - if (node == null) - { - throw new AVMNotFoundException("Not found: " + desc.getPath()); - } - List> paths = new ArrayList>(); - List components = new ArrayList(); - recursiveGetHeadPaths(node, components, paths); - return paths; - } - - /** - * Gets all the pass from to the given node starting from the give version root. - * - * @param version - * The version root. - * @param node - * The node to get the paths of. - * @return A list of all paths in the given version to the node. - */ - public List getVersionPaths(VersionRoot version, AVMNode node) - { - List paths = new ArrayList(); - List components = new ArrayList(); - recursiveGetVersionPaths(node, components, paths, version.getRoot(), version.getAvmStore().getName()); - return paths; - } - - /** - * Helper to get all version paths. - * - * @param node - * The current node we are examining. - * @param components - * The current path components. - * @param paths - * The list to contain found paths. - * @param root - * The root node of the version. - * @param storeName - * The name of the store. - */ - private void recursiveGetVersionPaths(AVMNode node, List components, List paths, DirectoryNode root, String storeName) - { - if (!can(null, node, PermissionService.READ_CHILDREN, false)) - { - return; - } - if (node.equals(root)) - { - paths.add(this.makePath(components, storeName)); - return; - } - List entries = fChildEntryDAO.getByChild(node); - for (ChildEntry entry : entries) - { - String name = entry.getKey().getName(); - components.add(name); - AVMNode parent = entry.getKey().getParent(); - recursiveGetVersionPaths(parent, components, paths, root, storeName); - components.remove(components.size() - 1); - } - } - - /** - * Get all paths in a particular store in the head version for a particular node. - * - * @param desc - * The node descriptor. - * @param store - * The name of the store. - * @return All matching paths. - */ - public List> getPathsInStoreHead(AVMNodeDescriptor desc, String store) - { - AVMStore st = getAVMStoreByName(store); - if (st == null) - { - throw new AVMNotFoundException("Store not found: " + store); - } - AVMNode node = fAVMNodeDAO.getByID(desc.getId()); - if (node == null) - { - throw new AVMNotFoundException("Not found: " + desc); - } - List> paths = new ArrayList>(); - List components = new ArrayList(); - recursiveGetPathsInStoreHead(node, components, paths, st.getRoot(), store); - return paths; - } - - /** - * Do the actual work. - * - * @param node - * The current node. - * @param components - * The currently accumulated path components. - * @param paths - * The list to put full paths in. - */ - private void recursiveGetPaths(AVMNode node, List components, List> paths) - { - if (!can(null, node, PermissionService.READ_CHILDREN, false)) - { - return; - } - if (node.getIsRoot()) - { - AVMStore store = fAVMStoreDAO.getByRoot(node); - if (store != null) - { - addPath(components, -1, store.getName(), paths); - } - VersionRoot vr = fVersionRootDAO.getByRoot(node); - if (vr != null) - { - addPath(components, vr.getVersionID(), vr.getAvmStore().getName(), paths); - } - return; - } - List entries = fChildEntryDAO.getByChild(node); - for (ChildEntry entry : entries) - { - String name = entry.getKey().getName(); - components.add(name); - AVMNode parent = entry.getKey().getParent(); - recursiveGetPaths(parent, components, paths); - components.remove(components.size() - 1); - } - } - - /** - * Do the work of getting one path for a node. - * - * @param node - * The node to get the path of. - * @param components - * The storage for path components. - * @return A path or null. - */ - private Pair recursiveGetAPath(AVMNode node, List components) - { - if (!can(null, node, PermissionService.READ_CHILDREN, false)) - { - return null; - } - if (node.getIsRoot()) - { - AVMStore store = fAVMStoreDAO.getByRoot(node); - if (store != null) - { - if (fgLogger.isDebugEnabled()) - { - fgLogger.debug("Found path in HEAD of: " + store.getName()); - } - return new Pair(-1, makePath(components, store.getName())); - } - VersionRoot vr = fVersionRootDAO.getByRoot(node); - if (vr != null) - { - if (fgLogger.isDebugEnabled()) - { - fgLogger.debug("Found path in version " + vr.getVersionID() + " in: " + vr.getAvmStore().getName()); - } - return new Pair(vr.getVersionID(), makePath(components, vr.getAvmStore().getName())); - } - return null; - } - List entries = fChildEntryDAO.getByChild(node); - for (ChildEntry entry : entries) - { - String name = entry.getKey().getName(); - if (fgLogger.isDebugEnabled()) - { - fgLogger.debug("Found component: " + name); - } - components.add(name); - Pair path = recursiveGetAPath(AVMNodeUnwrapper.Unwrap(entry.getKey().getParent()), components); - if (path != null) - { - return path; - } - components.remove(components.size() - 1); - } - return null; - } - - /** - * Do the actual work. - * - * @param node - * The current node. - * @param components - * The currently accumulated path components. - * @param paths - * The list to put full paths in. - */ - private void recursiveGetHeadPaths(AVMNode node, List components, List> paths) - { - if (!can(null, node, PermissionService.READ_CHILDREN, false)) - { - return; - } - if (node.getIsRoot()) - { - AVMStore store = fAVMStoreDAO.getByRoot(node); - if (store != null) - { - addPath(components, -1, store.getName(), paths); - return; - } - return; - } - List entries = fChildEntryDAO.getByChild(node); - for (ChildEntry entry : entries) - { - String name = entry.getKey().getName(); - components.add(name); - AVMNode parent = entry.getKey().getParent(); - recursiveGetHeadPaths(parent, components, paths); - components.remove(components.size() - 1); - } - } - - /** - * Do the actual work. - * - * @param node - * The current node. - * @param components - * The currently accumulated path components. - * @param paths - * The list to put full paths in. - */ - private void recursiveGetPathsInStoreHead(AVMNode node, List components, List> paths, DirectoryNode root, String storeName) - { - if (!can(null, node, PermissionService.READ_CHILDREN, false)) - { - return; - } - if (node.equals(root)) - { - addPath(components, -1, storeName, paths); - return; - } - List entries = fChildEntryDAO.getByChild(node); - for (ChildEntry entry : entries) - { - String name = entry.getKey().getName(); - components.add(name); - AVMNode parent = entry.getKey().getParent(); - recursiveGetHeadPaths(parent, components, paths); - components.remove(components.size() - 1); - } - } - - /** - * Add a path to the list. - * - * @param components - * The path name components. - * @param version - * The version id. - * @param storeName - * The name of the - * @param paths - * The List to add to. - */ - private void addPath(List components, int version, String storeName, List> paths) - { - paths.add(new Pair(version, makePath(components, storeName))); - } - - /** - * Alternate version. - * - * @param components - * @param storeName - * @param paths - */ - private void addPath(List components, String storeName, List paths) - { - paths.add(makePath(components, storeName)); - } - - /** - * Helper for generating paths. - * - * @param components - * The path components. - * @param storeName - * The store that the path is in. - * @return The path. - */ - private String makePath(List components, String storeName) - { - StringBuilder pathBuilder = new StringBuilder(); - pathBuilder.append(storeName); - pathBuilder.append(":"); - if (components.size() == 0) - { - pathBuilder.append("/"); - return pathBuilder.toString(); - } - for (int i = components.size() - 1; i >= 0; i--) - { - pathBuilder.append("/"); - pathBuilder.append(components.get(i)); - } - return pathBuilder.toString(); - } - - /** - * Get information about layering of a path. - * - * @param version - * The version to look under. - * @param path - * The full avm path. - * @return A LayeringDescriptor. - */ - public LayeringDescriptor getLayeringInfo(int version, String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - Lookup lookup = store.lookup(version, pathParts[1], false, true); - if (lookup == null) - { - throw new AVMNotFoundException("Path not found."); - } - if (!can(store, lookup.getCurrentNode(), PermissionService.READ_PROPERTIES, false)) - { - throw new AccessDeniedException("Not allowed to read properties: " + path); - } - return new LayeringDescriptor(!lookup.getDirectlyContained(), lookup.getAVMStore().getDescriptor(), lookup.getFinalStore().getDescriptor()); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Lookup a directory specifically. - * - * @param version - * The version to look under. - * @param path - * The path to lookup. - * @return A lookup object. - */ - public Lookup lookupDirectory(int version, String path) - { - Integer count = fLookupCount.get(); - try - { - if (count == null) - { - fLookupCount.set(1); - } - fLookupCount.set(fLookupCount.get() + 1); - if (fLookupCount.get() > 50) - { - throw new AVMCycleException("Cycle in lookup."); - } - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - return null; - } - return store.lookupDirectory(version, pathParts[1], false); - } - finally - { - if (count == null) - { - fLookupCount.set(null); - } - } - } - - /** - * Utility to split a path, foo:bar/baz into its repository and path parts. - * - * @param path - * The fully qualified path. - * @return The repository name and the repository path. - */ - private String[] SplitPath(String path) - { - String[] pathParts = path.split(":"); - if (pathParts.length != 2) - { - throw new AVMException("Invalid path: " + path); - } - return pathParts; - } - - /** - * Make a directory into a primary indirection. - * - * @param path - * The full path. - */ - public void makePrimary(String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.makePrimary(pathParts[1]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Change what a layered directory points at. - * - * @param path - * The full path to the layered directory. - * @param target - * The new target path. - */ - public void retargetLayeredDirectory(String path, String target) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.retargetLayeredDirectory(pathParts[1], target); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get the history chain for a node. - * - * @param desc - * The node to get history of. - * @param count - * The maximum number of ancestors to traverse. Negative means all. - * @return A List of ancestors. - */ - public List getHistory(AVMNodeDescriptor desc, int count) - { - AVMNode node = fAVMNodeDAO.getByID(desc.getId()); - if (node == null) - { - throw new AVMNotFoundException("Not found."); - } - if (!can(null, node, PermissionService.READ_PROPERTIES, false)) - { - throw new AccessDeniedException("Not allowed to read properties: " + desc); - } - if (count < 0) - { - count = Integer.MAX_VALUE; - } - List history = new ArrayList(); - for (int i = 0; i < count; i++) - { - node = node.getAncestor(); - if (node == null) - { - break; - } - if (!can(null, node, PermissionService.READ_PROPERTIES, false)) - { - break; - } - history.add(node.getDescriptor("UNKNOWN", "UNKNOWN", "UNKNOWN", -1)); - } - return history; - } - - /** - * Set the opacity of a layered directory. An opaque directory hides the things it points to via indirection. - * - * @param path - * The path to the layered directory. - * @param opacity - * True is opaque; false is not. - */ - public void setOpacity(String path, boolean opacity) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.setOpacity(pathParts[1], opacity); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Set a property on a node. - * - * @param path - * The path to the node. - * @param name - * The name of the property. - * @param value - * The value of the property. - */ - public void setNodeProperty(String path, QName name, PropertyValue value) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.setNodeProperty(pathParts[1], name, value); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Set a collection of properties at once. - * - * @param path - * The path to the node. - * @param properties - * The Map of QNames to PropertyValues. - */ - public void setNodeProperties(String path, Map properties) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.setNodeProperties(pathParts[1], properties); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get a property by name for a node. - * - * @param version - * The version to look under. - * @param path - * The path to the node. - * @param name - * The name of the property. - * @return The PropertyValue or null if it does not exist. - */ - public PropertyValue getNodeProperty(int version, String path, QName name) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getNodeProperty(version, pathParts[1], name); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get a Map of all the properties of a node. - * - * @param version - * The version to look under. - * @param path - * The path to the node. - * @return A Map of QNames to PropertyValues. - */ - public Map getNodeProperties(int version, String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getNodeProperties(version, pathParts[1]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Delete a single property from a node. - * - * @param path - * The path to the node. - * @param name - * The name of the property. - */ - public void deleteNodeProperty(String path, QName name) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.deleteNodeProperty(pathParts[1], name); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Delete all properties on a node. - * - * @param path - * The path to the node. - */ - public void deleteNodeProperties(String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.deleteNodeProperties(pathParts[1]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Set a property on a store. Overwrites if property exists. - * - * @param store - * The AVMStore. - * @param name - * The QName. - * @param value - * The PropertyValue to set. - */ - public void setStoreProperty(String store, QName name, PropertyValue value) - { - AVMStore st = getAVMStoreByName(store); - if (st == null) - { - throw new AVMNotFoundException("Store not found."); - } - st.setProperty(name, value); - } - - /** - * Set a group of properties on a store. Overwrites any properties that exist. - * - * @param store - * The AVMStore. - * @param props - * The properties to set. - */ - public void setStoreProperties(String store, Map props) - { - AVMStore st = getAVMStoreByName(store); - if (st == null) - { - throw new AVMNotFoundException("Store not found."); - } - st.setProperties(props); - } - - /** - * Get a property from a store. - * - * @param store - * The name of the store. - * @param name - * The property - * @return The property value or null if non-existent. - */ - public PropertyValue getStoreProperty(String store, QName name) - { - if (store == null) - { - throw new AVMBadArgumentException("Null store name."); - } - AVMStore st = getAVMStoreByName(store); - if (st == null) - { - throw new AVMNotFoundException("Store not found."); - } - return st.getProperty(name); - } - - /** - * Queries a given store for properties with keys that match a given pattern. - * - * @param store - * The name of the store. - * @param keyPattern - * The sql 'like' pattern, inserted into a QName. - * @return A Map of the matching key value pairs. - */ - @SuppressWarnings("unchecked") - public Map queryStorePropertyKey(String store, QName keyPattern) - { - AVMStore st = getAVMStoreByName(store); - if (st == null) - { - throw new AVMNotFoundException("Store not found."); - } - List matches = fAVMStorePropertyDAO.queryByKeyPattern(st, keyPattern); - Map matchesMap = new HashMap(); - for (AVMStoreProperty prop : matches) - { - matchesMap.put(prop.getQnameId(), prop.getValue()); - } - Map propertyMap = (Map) qnameDAO.convertIdMapToQNameMap(matchesMap); - return propertyMap; - } - - /** - * Queries all AVM stores for properties with keys that match a given pattern. - * - * @param keyPattern - * The sql 'like' pattern, inserted into a QName. - * @return A List of Pairs of Store name, Map.Entry. - */ - public Map> queryStoresPropertyKeys(QName keyPattern) - { - List matches = fAVMStorePropertyDAO.queryByKeyPattern(keyPattern); - Map> results = new HashMap>(); - for (AVMStoreProperty prop : matches) - { - String storeName = prop.getStore().getName(); - QName propQName = qnameDAO.getQName(prop.getQnameId()).getSecond(); - Map pairs = null; - if ((pairs = results.get(storeName)) == null) - { - pairs = new HashMap(); - results.put(storeName, pairs); - } - pairs.put(propQName, prop.getValue()); - } - return results; - } - - /** - * Get all the properties for a store. - * - * @param store - * The name of the Store. - * @return A Map of all the properties. - */ - public Map getStoreProperties(String store) - { - if (store == null) - { - throw new AVMBadArgumentException("Null store name."); - } - AVMStore st = getAVMStoreByName(store); - if (st == null) - { - throw new AVMNotFoundException("Store not found."); - } - return st.getProperties(); - } - - /** - * Delete a property from a store. - * - * @param store - * The name of the store. - * @param name - * The name of the property. - */ - public void deleteStoreProperty(String store, QName name) - { - AVMStore st = getAVMStoreByName(store); - if (st == null) - { - throw new AVMNotFoundException("Store not found."); - } - st.deleteProperty(name); - } - - /** - * Get the common ancestor of two nodes if one exists. Unfortunately this is a quadratic problem, taking time - * proportional to the product of the lengths of the left and right history chains. - * - * @param left - * The first node. - * @param right - * The second node. - * @return The common ancestor. There are four possible results. Null means that there is no common ancestor. Left - * returned means that left is strictly an ancestor of right. Right returned means that right is strictly an - * ancestor of left. Any other non null return is the common ancestor and indicates that left and right are - * in conflict. - */ - public AVMNodeDescriptor getCommonAncestor(AVMNodeDescriptor left, AVMNodeDescriptor right) - { - AVMNode lNode = fAVMNodeDAO.getByID(left.getId()); - AVMNode rNode = fAVMNodeDAO.getByID(right.getId()); - if (lNode == null || rNode == null) - { - throw new AVMNotFoundException("Node not found."); - } - if (!can(null, lNode, PermissionService.READ_PROPERTIES, false)) - { - throw new AccessDeniedException("Not allowed to read properties: " + left); - } - if (!can(null, rNode, PermissionService.READ_PROPERTIES, false)) - { - throw new AccessDeniedException("Not allowed to read properties: " + right); - } - // TODO Short changing the permissions checking here. I'm not sure - // if that's OK. - List leftHistory = new ArrayList(); - List rightHistory = new ArrayList(); - while (lNode != null || rNode != null) - { - boolean checkRight = false; - if (lNode != null) - { - leftHistory.add(lNode); - checkRight = true; - lNode = lNode.getAncestor(); - } - boolean checkLeft = false; - if (rNode != null) - { - rightHistory.add(rNode); - checkLeft = true; - rNode = rNode.getAncestor(); - } - if (checkRight) - { - AVMNode check = leftHistory.get(leftHistory.size() - 1); - for (AVMNode node : rightHistory) - { - if (node.equals(check)) - { - return node.getDescriptor("", "", "", -1); - } - } - } - if (checkLeft) - { - AVMNode check = rightHistory.get(rightHistory.size() - 1); - for (AVMNode node : leftHistory) - { - if (node.equals(check)) - { - return node.getDescriptor("", "", "", -1); - } - } - } - } - return null; - } - - /** - * Get the ContentData for a file. - * - * @param version - * The version to look under. - * @param path - * The path to the file. - * @return The ContentData for the file. - */ - public ContentData getContentDataForRead(int version, String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - return store.getContentDataForRead(version, pathParts[1]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get the ContentData for a file for writing. - * - * @param path - * The path to the file. - * @return The ContentData object. - */ - public ContentData getContentDataForWrite(String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - ContentData result = store.getContentDataForWrite(pathParts[1]); - return result; - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Set the ContentData on a file. - * - * @param path - * The path to the file. - * @param data - * The content data to set. - */ - public void setContentData(String path, ContentData data) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.setContentData(pathParts[1], data); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get the single instance of AVMRepository. - * - * @return The single instance. - */ - public static AVMRepository GetInstance() - { - return fgInstance; - } - - public void setMetaDataFrom(String path, AVMNodeDescriptor from) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found: " + pathParts[0]); - } - AVMNode fromNode = fAVMNodeDAO.getByID(from.getId()); - if (fromNode == null) - { - throw new AVMNotFoundException("Node not found: " + from.getPath()); - } - fLookupCache.onWrite(pathParts[0]); - store.setMetaDataFrom(pathParts[1], fromNode); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Add an aspect to an AVM Node. - * - * @param path - * The path to the node. - * @param aspectName - * The name of the aspect. - */ - public void addAspect(String path, QName aspectName) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.addAspect(pathParts[1], aspectName); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get all the aspects on an AVM node. - * - * @param version - * The version to look under. - * @param path - * The path to the node. - * @return A List of the QNames of the Aspects. - */ - public Set getAspects(int version, String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getAspects(version, pathParts[1]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Remove an aspect and all associated properties from a node. - * - * @param path - * The path to the node. - * @param aspectName - * The name of the aspect. - */ - public void removeAspect(String path, QName aspectName) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.removeAspect(pathParts[1], aspectName); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Does a node have a particular aspect. - * - * @param version - * The version to look under. - * @param path - * The path to the node. - * @param aspectName - * The name of the aspect. - * @return Whether the node has the aspect. - */ - public boolean hasAspect(int version, String path, QName aspectName) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.hasAspect(version, pathParts[1], aspectName); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Set the ACL on a node. - * - * @param path - * The path to the node. - * @param acl - * The ACL to set. - */ - public void setACL(String path, DbAccessControlList acl) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - store.setACL(pathParts[1], acl); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Get the ACL on a node. - * - * @param version - * The version to look under. - * @param path - * The path to the node. - * @return The ACL. - */ - public DbAccessControlList getACL(int version, String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - return store.getACL(version, pathParts[1]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Link a node into a directory, directly. - * - * @param parentPath - * The path to the parent. - * @param name - * The name to give the node. - * @param toLink - * The node to link. - */ - public void link(String parentPath, String name, AVMNodeDescriptor toLink) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(parentPath); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - store.link(pathParts[1], name, toLink); - fLookupCache.onWrite(pathParts[0]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Update a link, directly. - * - * @param parentPath - * The path to the parent. - * @param name - * The name to give the node. - * @param toLink - * The node to link. - */ - public void updateLink(String parentPath, String name, AVMNodeDescriptor toLink) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(parentPath); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - store.updateLink(pathParts[1], name, toLink); - fLookupCache.onWrite(pathParts[0]); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * This is the danger version of link. It must be called on a copied and unsnapshotted directory. It blithely - * inserts a child without checking if a child exists with a conflicting name. - * - * @param parent - * The parent directory. - * @param name - * The name to give the child. - * @param child - * The child to link in. - */ - public void link(AVMNodeDescriptor parent, String name, AVMNodeDescriptor child) - { - AVMNode node = fAVMNodeDAO.getByID(parent.getId()); - if (!(node instanceof DirectoryNode)) - { - throw new AVMWrongTypeException("Not a Directory."); - } - DirectoryNode dir = (DirectoryNode) node; - if (!dir.getIsNew()) - { - throw new AVMException("Directory has not already been copied."); - } - if (!can(null, dir, PermissionService.ADD_CHILDREN, false)) - { - throw new AccessDeniedException("Not allowed to write: " + parent); - } - dir.link(name, child); - } - - /** - * Remove name without leaving behind a deleted node. Dangerous if used unwisely. - * - * @param path - * The path to the layered directory. - * @param name - * The name of the child. - */ - public void flatten(String path, String name) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onDelete(pathParts[0]); - Lookup lPath = store.lookup(-1, pathParts[1], true, false); - AVMNode node = lPath.getCurrentNode(); - if (node == null) - { - throw new AVMNotFoundException("Path not found."); - } - if (!(node instanceof LayeredDirectoryNode)) - { - throw new AVMWrongTypeException("Not a Layered Directory."); - } - if (!can(store, node, PermissionService.FLATTEN, lPath.getDirectlyContained())) - { - throw new AccessDeniedException("Not allowed to write in: " + path); - } - LayeredDirectoryNode dir = (LayeredDirectoryNode) node; - dir.flatten(name); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Force a copy on write. - * - * @param path - * The path to force. - */ - public AVMNodeDescriptor forceCopy(String path) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onWrite(pathParts[0]); - // Just force a copy if needed by looking up in write mode. - Lookup lPath = store.lookup(-1, pathParts[1], true, true); - if (lPath == null) - { - throw new AVMNotFoundException("Path not found."); - } - AVMNode node = lPath.getCurrentNode(); - AVMNodeDescriptor desc = node.getDescriptor(lPath); - return desc; - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Rename a store. - * - * @param sourceName - * The original name. - * @param destName - * The new name. - * @throws AVMNotFoundException - * @throws AVMExistsException - */ - public void renameStore(String sourceName, String destName) - { - AlfrescoTransactionSupport.bindListener(fPurgeStoreTxnListener); - AlfrescoTransactionSupport.bindListener(fCreateStoreTxnListener); - AVMStore store = getAVMStoreByName(sourceName); - if (store == null) - { - throw new AVMNotFoundException("Store Not Found: " + sourceName); - } - if (getAVMStoreByName(destName) != null) - { - throw new AVMExistsException("Store Already Exists: " + destName); - } - if (!FileNameValidator.IsValid(destName)) - { - throw new AVMBadArgumentException("Bad store name: " + destName); - } - store.setName(destName); - store.createSnapshot("Rename Store", "Rename Store from " + sourceName + " to " + destName, new HashMap()); - fLookupCache.onDelete(sourceName); - fAVMStoreDAO.invalidateCache(); - fPurgeStoreTxnListener.storePurged(sourceName); - fCreateStoreTxnListener.storeCreated(destName); - } - - /** - * Revert a head path to a given version. This works by cloning the version to revert to, and then linking that new - * version into head. The reverted version will have the previous head version as ancestor. - * - * @param path - * The path to the parent directory. - * @param name - * The name of the node. - * @param toRevertTo - * The descriptor of the version to revert to. - */ - public void revert(String path, String name, AVMNodeDescriptor toRevertTo) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found: " + pathParts[0]); - } - fLookupCache.onWrite(pathParts[0]); - store.revert(pathParts[1], name, toRevertTo); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Set the GUID on a node. - * - * @param path - * @param guid - */ - public void setGuid(String path, String guid) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store not found:" + pathParts[0]); - } - fLookupCache.onWrite(pathParts[0]); - store.setGuid(pathParts[1], guid); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Set the encoding on a node. - * - * @param path - * @param encoding - */ - public void setEncoding(String path, String encoding) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store Not Found: " + pathParts[0]); - } - fLookupCache.onWrite(pathParts[0]); - store.setEncoding(pathParts[1], encoding); - } - finally - { - fLookupCount.set(null); - } - } - - /** - * Set the mime type on a node. - * - * @param path - * @param encoding - */ - public void setMimeType(String path, String mimeType) - { - fLookupCount.set(1); - try - { - String[] pathParts = SplitPath(path); - AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) - { - throw new AVMNotFoundException("Store Not Found: " + pathParts[0]); - } - fLookupCache.onWrite(pathParts[0]); - store.setMimeType(pathParts[1], mimeType); - } - finally - { - fLookupCount.set(null); - } - } - - public List getPathsInStoreVersion(AVMNodeDescriptor desc, String store, int version) - { - AVMNode node = fAVMNodeDAO.getByID(desc.getId()); - if (node == null) - { - throw new AVMNotFoundException("Not found: " + desc); - } - List paths = new ArrayList(); - List components = new ArrayList(); - recursiveGetStoreVersionPaths(store, node, version, components, paths); - return paths; - } - - /** - * Do the actual work. - * - * @param node - * The current node. - * @param components - * The currently accumulated path components. - * @param paths - * The list to put full paths in. - */ - private void recursiveGetStoreVersionPaths(String storeName, AVMNode node, int version, List components, List paths) - { - if (!can(null, node, PermissionService.READ, false)) - { - return; - } - if (node.getIsRoot()) - { - VersionRoot versionRoot = fVersionRootDAO.getByRoot(node); - if (versionRoot.getAvmStore().getName().equals(storeName) && versionRoot.getVersionID() == version) - { - addPath(components, storeName, paths); - return; - } - return; - } - List entries = fChildEntryDAO.getByChild(node); - for (ChildEntry entry : entries) - { - String name = entry.getKey().getName(); - components.add(name); - AVMNode parent = entry.getKey().getParent(); - recursiveGetStoreVersionPaths(storeName, parent, version, components, paths); - components.remove(components.size() - 1); - } - } - - public Map getNodeProperties(AVMNodeDescriptor desc) - { - AVMNode node = fAVMNodeDAO.getByID(desc.getId()); - if (node == null) - { - throw new AVMNotFoundException("Node not found: " + desc); - } - if (!can(null, node, PermissionService.READ_PROPERTIES, false)) - { - throw new AccessDeniedException("Not allowed to read properties: " + desc); - } - QNameDAO qnameDAO = AVMDAOs.Instance().fQNameDAO; - @SuppressWarnings("unchecked") - Map converted = (Map) qnameDAO.convertIdMapToQNameMap(node.getProperties()); - return converted; - } - - public ContentData getContentDataForRead(AVMNodeDescriptor desc) - { - AVMNode node = fAVMNodeDAO.getByID(desc.getId()); - if (node == null) - { - throw new AVMNotFoundException("Node not found: " + desc); - } - if (!can(null, node, PermissionService.READ_CONTENT, false)) - { - throw new AccessDeniedException("Not allowed to read: " + desc); - } - if (node.getType() == AVMNodeType.PLAIN_FILE) - { - PlainFileNode file = (PlainFileNode) node; - return file.getContentData(); - } - throw new AVMWrongTypeException("Not a Plain File: " + desc); - } - - public Set getAspects(AVMNodeDescriptor desc) - { - AVMNode node = fAVMNodeDAO.getByID(desc.getId()); - if (node == null) - { - throw new AVMNotFoundException("Node not found: " + desc); - } - if (!can(null, node, PermissionService.READ_PROPERTIES, false)) - { - throw new AccessDeniedException("Not allowed to read properties: " + desc); - } - Set aspectIds = node.getAspects(); - // Convert to QNames - Set aspectQNames = qnameDAO.convertIdsToQNames(aspectIds); - return aspectQNames; - } - - /** - * Evaluate permission on a node. I've got a bad feeling about this... - * - * @param store - * @param node - * @param permission - * @return - */ - public boolean can(AVMStore store, AVMNode node, String permission, boolean isDirectlyContained) - { - DbAccessControlList acl = node.getAcl(); - - QName type; - if (node.getType() == AVMNodeType.PLAIN_DIRECTORY) - { - type = WCMModel.TYPE_AVM_PLAIN_FOLDER; - } - else if (node.getType() == AVMNodeType.PLAIN_FILE) - { - type = WCMModel.TYPE_AVM_PLAIN_CONTENT; - } - else if (node.getType() == AVMNodeType.LAYERED_DIRECTORY) - { - type = WCMModel.TYPE_AVM_LAYERED_FOLDER; - } - else - { - type = WCMModel.TYPE_AVM_LAYERED_CONTENT; - } - PermissionContext context = new PermissionContext(type); - - // We're doing the hand unrolling of the proxy because Hibernate/CGLIB proxies are broken - context.addDynamicAuthorityAssignment(AVMNodeUnwrapper.Unwrap(node).getBasicAttributes().getOwner(), PermissionService.OWNER_AUTHORITY); - - if ((store != null) && isDirectlyContained) - { - StoreType storeType = StoreType.getStoreType(store.getName(), store.getDescriptor(), store.getProperties()); - switch (storeType) - { - case AUTHOR: - case AUTHOR_PREVIEW: - case AUTHOR_WORKFLOW: - case AUTHOR_WORKFLOW_PREVIEW: - String storeName = store.getName(); - int first = -1; - int second = -1; - first = storeName.indexOf("--"); - if (first >= 0) - { - second = storeName.indexOf("--", first + 2); - String storeOwner; - if (second >= 0) - { - storeOwner = storeName.substring(first + 2, second); - } - else - { - storeOwner = storeName.substring(first + 2); - } - context.addDynamicAuthorityAssignment(storeOwner, PermissionService.WCM_STORE_OWNER_AUTHORITY); - } - break; - case STAGING: - case STAGING_PREVIEW: - case UNKNOWN: - case WORKFLOW: - case WORKFLOW_PREVIEW: - default: - } - - } - // Pass in node aspects - Set nodeAspectQNames = qnameDAO.convertIdsToQNames(node.getAspects()); - Set contextQNames = context.getAspects(); - contextQNames.addAll(nodeAspectQNames); - // Pass in node properties - Map nodeProperties = node.getProperties(); - Map contextProperties = new HashMap(5); - QNameDAO qnameDAO = AVMDAOs.Instance().fQNameDAO; - for (Map.Entry entry : nodeProperties.entrySet()) - { - QName qname = qnameDAO.getQName(entry.getKey()).getSecond(); - PropertyDefinition def = fDictionaryService.getProperty(qname); - if (def == null) - { - contextProperties.put(qname, entry.getValue().getValue(DataTypeDefinition.ANY)); - } - else - { - contextProperties.put(qname, entry.getValue().getValue(def.getDataType().getName())); - } - } - context.getProperties().putAll(contextProperties); - Long aclId = null; - if (acl != null) - { - aclId = acl.getId(); - } - if (store != null) - { - DbAccessControlList storeAcl = store.getStoreAcl(); - if (storeAcl != null) - { - Long storeAclID = storeAcl.getId(); - context.setStoreAcl(storeAclID); - } - } - return fPermissionService.hasPermission(aclId, context, permission) == AccessStatus.ALLOWED; - } - - public boolean can(String storeName, int version, String path, String permission) - { - Lookup lookup = AVMRepository.GetInstance().lookup(version, path, true); - if (lookup != null) - { - AVMNode node = lookup.getCurrentNode(); - AVMStore store = getAVMStoreByName(storeName); - return can(store, node, permission, lookup.getDirectlyContained()); - } - else - { - // Does not exist => allowed - return true; - } - } - - /** - * Set the acl on a store. - * - * @param storeName - * @param acl - */ - public void setStoreAcl(String storeName, DbAccessControlList acl) - { - AVMStore store = getAVMStoreByName(storeName); - if (store == null) - { - throw new AVMNotFoundException("Store not found: " + storeName); - } - store.setStoreAcl(acl); - } - - /** - * Get the ACL on a store. - * - * @param storeName - * @return - */ - public DbAccessControlList getStoreAcl(String storeName) - { - AVMStore store = getAVMStoreByName(storeName); - if (store == null) - { - throw new AVMNotFoundException("Store not found: " + storeName); - } - return store.getStoreAcl(); - } -} +/* + * Copyright (C) 2005-2009 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" */ + +package org.alfresco.repo.avm; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; + +import org.alfresco.model.WCMModel; +import org.alfresco.repo.content.ContentStore; +import org.alfresco.repo.domain.DbAccessControlList; +import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.domain.QNameDAO; +import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor.StoreType; +import org.alfresco.repo.security.permissions.ACLCopyMode; +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport; +import org.alfresco.service.cmr.avm.AVMBadArgumentException; +import org.alfresco.service.cmr.avm.AVMCycleException; +import org.alfresco.service.cmr.avm.AVMException; +import org.alfresco.service.cmr.avm.AVMExistsException; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMNotFoundException; +import org.alfresco.service.cmr.avm.AVMStoreDescriptor; +import org.alfresco.service.cmr.avm.AVMWrongTypeException; +import org.alfresco.service.cmr.avm.LayeringDescriptor; +import org.alfresco.service.cmr.avm.VersionDescriptor; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionContext; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This or AVMStore are the implementors of the operations specified by AVMService. + * + * @author britt + */ +public class AVMRepository +{ + private static Log fgLogger = LogFactory.getLog(AVMRepository.class); + + /** + * The single instance of AVMRepository. + */ + private static AVMRepository fgInstance; + + /** + * The current lookup count. + */ + private ThreadLocal fLookupCount; + + /** + * Reference to the ContentStoreImpl + */ + private ContentStore fContentStore; + + /** + * The Lookup Cache instance. + */ + private LookupCache fLookupCache; + + private QNameDAO qnameDAO; + + private AVMStoreDAO fAVMStoreDAO; + + private AVMNodeDAO fAVMNodeDAO; + + private VersionRootDAO fVersionRootDAO; + + private VersionLayeredNodeEntryDAO fVersionLayeredNodeEntryDAO; + + private AVMStorePropertyDAO fAVMStorePropertyDAO; + + private ChildEntryDAO fChildEntryDAO; + + private PermissionService fPermissionService; + + private DictionaryService fDictionaryService; + + // A bunch of TransactionListeners that do work for this. + + /** + * One for create store. + */ + private CreateStoreTxnListener fCreateStoreTxnListener; + + /** + * One for purge store. + */ + private PurgeStoreTxnListener fPurgeStoreTxnListener; + + /** + * One for create version. + */ + private CreateVersionTxnListener fCreateVersionTxnListener; + + /** + * One for purge version. + */ + private PurgeVersionTxnListener fPurgeVersionTxnListener; + + /** + * Create a new one. + */ + public AVMRepository() + { + fLookupCount = new ThreadLocal(); + fgInstance = this; + } + + /** + * Set the ContentService. + */ + public void setContentStore(ContentStore store) + { + fContentStore = store; + } + + /** + * Set the Lookup Cache instance. + * + * @param cache + * The instance to set. + */ + public void setLookupCache(LookupCache cache) + { + fLookupCache = cache; + } + + public void setCreateStoreTxnListener(CreateStoreTxnListener listener) + { + fCreateStoreTxnListener = listener; + } + + public void setPurgeStoreTxnListener(PurgeStoreTxnListener listener) + { + fPurgeStoreTxnListener = listener; + } + + public void setCreateVersionTxnListener(CreateVersionTxnListener listener) + { + fCreateVersionTxnListener = listener; + } + + public void setPurgeVersionTxnListener(PurgeVersionTxnListener listener) + { + fPurgeVersionTxnListener = listener; + } + + public void setQnameDAO(QNameDAO qnameDAO) + { + this.qnameDAO = qnameDAO; + } + + public void setAvmStoreDAO(AVMStoreDAO dao) + { + fAVMStoreDAO = dao; + } + + public void setAvmNodeDAO(AVMNodeDAO dao) + { + fAVMNodeDAO = dao; + } + + public void setVersionRootDAO(VersionRootDAO dao) + { + fVersionRootDAO = dao; + } + + public void setVersionLayeredNodeEntryDAO(VersionLayeredNodeEntryDAO dao) + { + fVersionLayeredNodeEntryDAO = dao; + } + + public void setAvmStorePropertyDAO(AVMStorePropertyDAO dao) + { + fAVMStorePropertyDAO = dao; + } + + public void setChildEntryDAO(ChildEntryDAO dao) + { + fChildEntryDAO = dao; + } + + public void setPermissionService(PermissionService service) + { + fPermissionService = service; + } + + public void setDictionaryService(DictionaryService service) + { + fDictionaryService = service; + } + + /** + * Create a file. + * + * @param path + * The path to the containing directory. + * @param name + * The name for the new file. + */ + public OutputStream createFile(String path, String name) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + OutputStream out = store.createFile(pathParts[1], name); + return out; + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Create a file with the given File as content. + * + * @param path + * The path to the containing directory. + * @param name + * The name to give the file. + * @param data + * The file contents. + */ + public void createFile(String path, String name, File data, List aspects, Map properties) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.createFile(pathParts[1], name, data, aspects, properties); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Create a new directory. + * + * @param path + * The path to the containing directory. + * @param name + * The name to give the directory. + */ + public void createDirectory(String path, String name, List aspects, Map properties) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.createDirectory(pathParts[1], name, aspects, properties); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Create a new directory. This assumes that the parent is already copied and therefore should only be used with + * great care. + * + * @param parent + * The parent node. + * @param name + * The name of the new directory. + * @return A descriptor for the newly created directory. + */ + public AVMNodeDescriptor createDirectory(AVMNodeDescriptor parent, String name) + { + AVMNode node = fAVMNodeDAO.getByID(parent.getId()); + if (node == null) + { + throw new AVMNotFoundException(parent.getId() + " not found."); + } + if (!(node instanceof DirectoryNode)) + { + throw new AVMWrongTypeException("Not a directory."); + } + if (!can(null, node, PermissionService.CREATE_CHILDREN, true)) + { + throw new AccessDeniedException("Not allowed to write in: " + parent); + } + // We need the store to do anything so... + String[] pathParts = SplitPath(parent.getPath()); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + DirectoryNode dir = (DirectoryNode) node; + DirectoryNode child = null; + Long parentAcl = dir.getAcl() == null ? null : dir.getAcl().getId(); + if (dir instanceof LayeredDirectoryNode) + { + child = new LayeredDirectoryNodeImpl((String) null, store, null, parentAcl, ACLCopyMode.INHERIT); + ((LayeredDirectoryNode) child).setPrimaryIndirection(false); + ((LayeredDirectoryNode) child).setLayerID(parent.getLayerID()); + } + else + { + child = new PlainDirectoryNodeImpl(store); + } + dir.putChild(name, child); + DbAccessControlList acl = dir.getAcl(); + child.setAcl(acl != null ? acl.getCopy(acl.getId(), ACLCopyMode.INHERIT) : null); + fLookupCache.onWrite(pathParts[0]); + AVMNodeDescriptor desc = child.getDescriptor(parent.getPath(), name, parent.getIndirection(), parent.getIndirectionVersion()); + return desc; + } + + /** + * Create a new layered directory. + * + * @param srcPath + * The target indirection for the new layered directory. + * @param dstPath + * The path to the containing directory. + * @param name + * The name for the new directory. + */ + public void createLayeredDirectory(String srcPath, String dstPath, String name) + { + if (dstPath.indexOf(srcPath) == 0) + { + throw new AVMCycleException("Cycle would be created."); + } + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(dstPath); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.createLayeredDirectory(srcPath, pathParts[1], name); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Create a new layered file. + * + * @param srcPath + * The target indirection for the new layered file. + * @param dstPath + * The path to the containing directory. + * @param name + * The name of the new layered file. + */ + public void createLayeredFile(String srcPath, String dstPath, String name) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(dstPath); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.createLayeredFile(srcPath, pathParts[1], name); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Create a new AVMStore. + * + * @param name + * The name to give the new AVMStore. + */ + public void createAVMStore(String name) + { + AlfrescoTransactionSupport.bindListener(fCreateStoreTxnListener); + if (getAVMStoreByName(name) != null) + { + throw new AVMExistsException("AVMStore exists: " + name); + } + // Newing up the object causes it to be written to the db. + AVMStore rep = new AVMStoreImpl(this, name); + // Special handling for AVMStore creation. + rep.getRoot().setStoreNew(null); + fCreateStoreTxnListener.storeCreated(name); + } + + /** + * Create a new branch. + * + * @param version + * The version to branch off. + * @param srcPath + * The path to make a branch from. + * @param dstPath + * The containing directory. + * @param name + * The name of the new branch. + */ + public void createBranch(int version, String srcPath, String dstPath, String name) + { + if (dstPath.indexOf(srcPath) == 0) + { + throw new AVMCycleException("Cycle would be created."); + } + // Lookup the src node. + fLookupCount.set(1); + String[] pathParts; + Lookup sPath; + List layeredEntries = null; + try + { + pathParts = SplitPath(srcPath); + AVMStore srcRepo = getAVMStoreByName(pathParts[0]); + if (srcRepo == null) + { + throw new AVMNotFoundException("Store not found."); + } + if (version < 0) + { + fLookupCache.onSnapshot(pathParts[0]); + version = srcRepo.createSnapshot("Branch Snapshot", null, new HashMap()).get(pathParts[0]); + } + sPath = srcRepo.lookup(version, pathParts[1], false, false); + if (sPath == null) + { + throw new AVMNotFoundException("Path not found."); + } + VersionRoot lastVersion = fVersionRootDAO.getByVersionID(srcRepo, version); + layeredEntries = fVersionLayeredNodeEntryDAO.get(lastVersion); + } + finally + { + fLookupCount.set(null); + } + // Lookup the destination directory. + fLookupCount.set(1); + try + { + pathParts = SplitPath(dstPath); + AVMStore dstRepo = getAVMStoreByName(pathParts[0]); + if (dstRepo == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1], true); + if (dPath == null) + { + throw new AVMNotFoundException("Path not found."); + } + DirectoryNode dirNode = (DirectoryNode) dPath.getCurrentNode(); + if (!can(dstRepo, dirNode, PermissionService.ADD_CHILDREN, dPath.getDirectlyContained())) + { + throw new AccessDeniedException("Not permitted to add children: " + dstPath); + } + AVMNode srcNode = sPath.getCurrentNode(); + AVMNode dstNode = null; + // We do different things depending on what kind of thing we're + // branching from. I'd be considerably happier if we disallowed + // certain scenarios, but Jon won't let me :P (bhp). + + Long inheritAcl = srcNode.getAcl() == null ? null : srcNode.getAcl().getId(); + + if (srcNode.getType() == AVMNodeType.PLAIN_DIRECTORY) + { + dstNode = new PlainDirectoryNodeImpl((PlainDirectoryNode) srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); + } + else if (srcNode.getType() == AVMNodeType.LAYERED_DIRECTORY) + { + dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, sPath, false, inheritAcl, ACLCopyMode.INHERIT); + + // note: re-use generated node id as a layer id + ((LayeredDirectoryNode) dstNode).setLayerID(dstNode.getId()); + } + else if (srcNode.getType() == AVMNodeType.LAYERED_FILE) + { + dstNode = new LayeredFileNodeImpl((LayeredFileNode) srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); + } + else + // This is a plain file. + { + dstNode = new PlainFileNodeImpl((PlainFileNode) srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); + } + // dstNode.setVersionID(dstRepo.getNextVersionID()); + dstNode.setAncestor(srcNode); + dirNode.putChild(name, dstNode); + // dirNode.updateModTime(); + String beginingPath = AVMNodeConverter.NormalizePath(srcPath); + String finalPath = AVMNodeConverter.ExtendAVMPath(dstPath, name); + finalPath = AVMNodeConverter.NormalizePath(finalPath); + VersionRoot latestVersion = fVersionRootDAO.getMaxVersion(dstRepo); + for (VersionLayeredNodeEntry entry : layeredEntries) + { + String path = entry.getPath(); + if (!path.startsWith(srcPath)) + { + continue; + } + String newPath = finalPath + path.substring(beginingPath.length()); + VersionLayeredNodeEntry newEntry = new VersionLayeredNodeEntryImpl(latestVersion, newPath); + fVersionLayeredNodeEntryDAO.save(newEntry); + } + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get an output stream to a file. + * + * @param path + * The full path to the file. + * @return An OutputStream. + */ + public OutputStream getOutputStream(String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + OutputStream out = store.getOutputStream(pathParts[1]); + return out; + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get a content reader from a file node. + * + * @param version + * The version of the file. + * @param path + * The path to the file. + * @return A ContentReader. + */ + public ContentReader getContentReader(int version, String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found: " + pathParts[0]); + } + return store.getContentReader(version, pathParts[1]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get a ContentWriter to a file node. + * + * @param path + * The path to the file. + * @return A ContentWriter. + */ + public ContentWriter createContentWriter(String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found: " + pathParts[0]); + } + fLookupCache.onWrite(pathParts[0]); + ContentWriter writer = store.createContentWriter(pathParts[1]); + return writer; + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Rename a node. + * + * @param srcPath + * Source containing directory. + * @param srcName + * Source name. + * @param dstPath + * Destination containing directory. + * @param dstName + * Destination name. + */ + public void rename(String srcPath, String srcName, String dstPath, String dstName) + { + // This is about as ugly as it gets. + if ((dstPath + "/").indexOf(srcPath + srcName + "/") == 0) + { + throw new AVMCycleException("Cyclic rename."); + } + fLookupCount.set(1); + String[] pathParts; + Lookup sPath; + DirectoryNode srcDir; + AVMNode srcNode; + try + { + pathParts = SplitPath(srcPath); + AVMStore srcRepo = getAVMStoreByName(pathParts[0]); + if (srcRepo == null) + { + throw new AVMNotFoundException("Store not found."); + } + sPath = srcRepo.lookupDirectory(-1, pathParts[1], true); + if (sPath == null) + { + throw new AVMNotFoundException("Path not found."); + } + srcDir = (DirectoryNode) sPath.getCurrentNode(); + + Pair temp = srcDir.lookupChild(sPath, srcName, false); + srcNode = (temp == null) ? null : temp.getFirst(); + if (srcNode == null) + { + throw new AVMNotFoundException("Not found: " + srcName); + } + if (!can(srcRepo, srcNode, PermissionService.DELETE_NODE, false)) + { + throw new AccessDeniedException("Not allowed to delete target: " + srcPath); + } + + fLookupCache.onDelete(pathParts[0]); + } + finally + { + fLookupCount.set(null); + } + fLookupCount.set(1); + try + { + pathParts = SplitPath(dstPath); + AVMStore dstRepo = getAVMStoreByName(pathParts[0]); + if (dstRepo == null) + { + throw new AVMNotFoundException("Store not found."); + } + Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1], true); + if (dPath == null) + { + throw new AVMNotFoundException("Path not found."); + } + DirectoryNode dstDir = (DirectoryNode) dPath.getCurrentNode(); + if (!can(dstRepo, dstDir, PermissionService.ADD_CHILDREN, dPath.getDirectlyContained())) + { + throw new AccessDeniedException("Not allowed to write: " + dstPath); + } + Pair temp = dstDir.lookupChild(dPath, dstName, true); + AVMNode child = (temp == null) ? null : temp.getFirst(); + if (child != null && child.getType() != AVMNodeType.DELETED_NODE) + { + throw new AVMExistsException("Node exists: " + dstName); + } + + Long parentAcl = dstDir.getAcl() == null ? null : dstDir.getAcl().getId(); + + AVMNode dstNode = null; + // We've passed the check, so we can go ahead and do the rename. + if (srcNode.getType() == AVMNodeType.PLAIN_DIRECTORY) + { + // If the source is layered then the renamed thing needs to be layered also. + if (sPath.isLayered()) + { + // If this is a rename happening in the same layer we make a new + // OverlayedDirectoryNode that is not a primary indirection layer. + // Otherwise we do make the new OverlayedDirectoryNode a primary + // Indirection layer. This complexity begs the question of whether + // we should allow renames from within one layer to within another + // layer. Allowing it makes the logic absurdly complex. + if (dPath.isLayered() && dPath.getTopLayer().equals(sPath.getTopLayer())) + { + dstNode = new LayeredDirectoryNodeImpl((PlainDirectoryNode) srcNode, dstRepo, sPath, true, parentAcl, ACLCopyMode.COPY); + ((LayeredDirectoryNode) dstNode).setLayerID(sPath.getTopLayer().getLayerID()); + } + else + { + dstNode = new LayeredDirectoryNodeImpl((DirectoryNode) srcNode, dstRepo, sPath, srcName, parentAcl, ACLCopyMode.COPY); + + // note: re-use generated node id as a layer id + ((LayeredDirectoryNode) dstNode).setLayerID(dstNode.getId()); + } + } + else + { + dstNode = new PlainDirectoryNodeImpl((PlainDirectoryNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); + } + } + else if (srcNode.getType() == AVMNodeType.LAYERED_DIRECTORY) + { + if (!sPath.isLayered() || (sPath.isInThisLayer() && srcDir.getType() == AVMNodeType.LAYERED_DIRECTORY && ((LayeredDirectoryNode) srcDir).directlyContains(srcNode))) + { + Lookup srcLookup = lookup(-1, srcPath + "/" + srcName, true); + // Use the simple 'copy' constructor. + dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, srcLookup, true, parentAcl, ACLCopyMode.COPY); + ((LayeredDirectoryNode) dstNode).setLayerID(((LayeredDirectoryNode) srcNode).getLayerID()); + } + else + { + // If the source node is a primary indirection, then the 'copy' constructor + // is used. Otherwise the alternate constructor is called and its + // indirection is calculated from it's source context. + if (((LayeredDirectoryNode) srcNode).getPrimaryIndirection()) + { + Lookup srcLookup = lookup(-1, srcPath + "/" + srcName, true); + dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, srcLookup, true, parentAcl, ACLCopyMode.COPY); + } + else + { + dstNode = new LayeredDirectoryNodeImpl((DirectoryNode) srcNode, dstRepo, sPath, srcName, parentAcl, ACLCopyMode.COPY); + } + // What needs to be done here is dependent on whether the + // rename is to a layered context. If so then it should get the layer id + // of its destination parent. Otherwise it should get a new layer + // id. + if (dPath.isLayered()) + { + ((LayeredDirectoryNode) dstNode).setLayerID(dPath.getTopLayer().getLayerID()); + } + else + { + // note: re-use generated node id as a layer id + ((LayeredDirectoryNode) dstNode).setLayerID(dstNode.getId()); + } + } + } + else if (srcNode.getType() == AVMNodeType.LAYERED_FILE) + { + dstNode = new LayeredFileNodeImpl((LayeredFileNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); + } + else + // This is a plain file node. + { + dstNode = new PlainFileNodeImpl((PlainFileNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); + } + srcDir.removeChild(sPath, srcName); + // srcDir.updateModTime(); + // dstNode.setVersionID(dstRepo.getNextVersionID()); + if (child != null) + { + dstNode.setAncestor(child); + } + //dstDir.updateModTime(); + dstDir.putChild(dstName, dstNode); + if (child == null) + { + dstNode.setAncestor(srcNode); + } + fLookupCache.onWrite(pathParts[0]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Uncover a deleted name in a layered directory. + * + * @param dirPath + * The path to the layered directory. + * @param name + * The name to uncover. + */ + public void uncover(String dirPath, String name) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(dirPath); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.uncover(pathParts[1], name); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Create a snapshot of a single AVMStore. + * + * @param store + * The name of the repository. + * @param tag + * The short description. + * @param description + * The thick description. + * @return The version id of the newly snapshotted repository. + */ + public Map createSnapshot(String storeName, String tag, String description) + { + try + { + fAVMNodeDAO.noCache(); + AlfrescoTransactionSupport.bindListener(fCreateVersionTxnListener); + AVMStore store = getAVMStoreByName(storeName); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + Map result = store.createSnapshot(tag, description, new HashMap()); + for (Map.Entry entry : result.entrySet()) + { + fLookupCache.onSnapshot(entry.getKey()); + fCreateVersionTxnListener.versionCreated(entry.getKey(), entry.getValue()); + } + return result; + } + finally + { + fAVMNodeDAO.yesCache(); + } + } + + /** + * Remove a node and everything underneath it. + * + * @param path + * The path to the containing directory. + * @param name + * The name of the node to remove. + */ + public void remove(String path, String name) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onDelete(pathParts[0]); + store.removeNode(pathParts[1], name); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get rid of all content that lives only in the given AVMStore. Also removes the AVMStore. + * + * @param name + * The name of the AVMStore to purge. + */ + public void purgeAVMStore(String name) + { + AlfrescoTransactionSupport.bindListener(fPurgeStoreTxnListener); + AVMStore store = getAVMStoreByName(name); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onDelete(name); + AVMNode root = store.getRoot(); + // TODO Probably a special PermissionService.PURGE is needed. + if (!can(store, root, PermissionService.DELETE_CHILDREN, true)) + { + throw new AccessDeniedException("Not allowed to purge: " + name); + } + root.setIsRoot(false); + List vRoots = fVersionRootDAO.getAllInAVMStore(store); + for (VersionRoot vr : vRoots) + { + AVMNode node = vr.getRoot(); + node.setIsRoot(false); + fVersionLayeredNodeEntryDAO.delete(vr); + fVersionRootDAO.delete(vr); + } + List newGuys = fAVMNodeDAO.getNewInStore(store); + for (AVMNode newGuy : newGuys) + { + newGuy.setStoreNew(null); + } + fAVMStorePropertyDAO.delete(store); + fAVMStoreDAO.delete(store); + fAVMStoreDAO.invalidateCache(); + fPurgeStoreTxnListener.storePurged(name); + } + + /** + * Remove all content specific to a AVMRepository and version. + * + * @param name + * The name of the AVMStore. + * @param version + * The version to purge. + */ + public void purgeVersion(String name, int version) + { + AlfrescoTransactionSupport.bindListener(fPurgeVersionTxnListener); + AVMStore store = getAVMStoreByName(name); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onDelete(name); + store.purgeVersion(version); + fPurgeVersionTxnListener.versionPurged(name, version); + } + + /** + * Get an input stream from a file. + * + * @param version + * The version to look under. + * @param path + * The path to the file. + * @return An InputStream. + */ + public InputStream getInputStream(int version, String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getInputStream(version, pathParts[1]); + } + finally + { + fLookupCount.set(null); + } + } + + public InputStream getInputStream(AVMNodeDescriptor desc) + { + AVMNode node = fAVMNodeDAO.getByID(desc.getId()); + if (!(node instanceof FileNode)) + { + throw new AVMWrongTypeException(desc + " is not a File."); + } + if (!can(null, node, PermissionService.READ_CONTENT, false)) + { + throw new AccessDeniedException("Not allowed to read content: " + desc); + } + FileNode file = (FileNode) node; + ContentData data = file.getContentData(null); + if (data == null) + { + throw new AVMException(desc + " has no content."); + } + ContentReader reader = fContentStore.getReader(data.getContentUrl()); + return reader.getContentInputStream(); + } + + /** + * Get a listing of a directory. + * + * @param version + * The version to look under. + * @param path + * The path to the directory. + * @param includeDeleted + * Whether to see DeletedNodes. + * @return A List of FolderEntries. + */ + public SortedMap getListing(int version, String path, boolean includeDeleted) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getListing(version, pathParts[1], includeDeleted); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get the list of nodes directly contained in a directory. + * + * @param version + * The version to look under. + * @param path + * The path to the directory to list. + * @return A Map of names to descriptors. + */ + public SortedMap getListingDirect(int version, String path, boolean includeDeleted) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getListingDirect(version, pathParts[1], includeDeleted); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get the list of nodes directly contained in a directory. + * + * @param dir + * The descriptor to the directory node. + * @param includeDeleted + * Whether to include deleted children. + * @return A Map of names to descriptors. + */ + public SortedMap getListingDirect(AVMNodeDescriptor dir, boolean includeDeleted) + { + AVMNode node = fAVMNodeDAO.getByID(dir.getId()); + if (node == null) + { + throw new AVMBadArgumentException("Invalid Node."); + } + if (!can(null, node, PermissionService.READ_CHILDREN, false)) + { + throw new AccessDeniedException("Not allowed to read children: " + dir); + } + if (node.getType() == AVMNodeType.PLAIN_DIRECTORY) + { + return getListing(dir, includeDeleted); + } + if (node.getType() != AVMNodeType.LAYERED_DIRECTORY) + { + throw new AVMWrongTypeException("Not a directory."); + } + LayeredDirectoryNode dirNode = (LayeredDirectoryNode) node; + return dirNode.getListingDirect(dir, includeDeleted); + } + + /** + * Get a directory listing from a directory node descriptor. + * + * @param dir + * The directory node descriptor. + * @return A SortedMap listing. + */ + public SortedMap getListing(AVMNodeDescriptor dir, boolean includeDeleted) + { + fLookupCount.set(1); + try + { + AVMNode node = fAVMNodeDAO.getByID(dir.getId()); + if (node == null) + { + throw new AVMBadArgumentException("Invalid Node."); + } + if (node.getType() != AVMNodeType.LAYERED_DIRECTORY && node.getType() != AVMNodeType.PLAIN_DIRECTORY) + { + throw new AVMWrongTypeException("Not a directory."); + } + if (!can(null, node, PermissionService.READ_CHILDREN, false)) + { + throw new AccessDeniedException("Not allowed to read children: " + dir); + } + DirectoryNode dirNode = (DirectoryNode) node; + SortedMap listing = dirNode.getListing(dir, includeDeleted); + return listing; + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get a directory listing from a directory node descriptor fo children that match the given pattern + * + * @param dir + * The directory node descriptor. + * @return A SortedMap listing. + */ + public SortedMap getListing(AVMNodeDescriptor dir, String childNamePattern, boolean includeDeleted) + { + fLookupCount.set(1); + try + { + AVMNode node = fAVMNodeDAO.getByID(dir.getId()); + if (node == null) + { + throw new AVMBadArgumentException("Invalid Node."); + } + if (node.getType() != AVMNodeType.LAYERED_DIRECTORY && node.getType() != AVMNodeType.PLAIN_DIRECTORY) + { + throw new AVMWrongTypeException("Not a directory."); + } + if (!can(null, node, PermissionService.READ_CHILDREN, false)) + { + throw new AccessDeniedException("Not allowed to read children: " + dir); + } + DirectoryNode dirNode = (DirectoryNode) node; + SortedMap listing = dirNode.getListing(dir, childNamePattern, includeDeleted); + return listing; + } + finally + { + fLookupCount.set(null); + } + } + + + /** + * Get the names of deleted nodes in a directory. + * + * @param version + * The version to look under. + * @param path + * The path to the directory. + * @return A List of names. + */ + public List getDeleted(int version, String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getDeleted(version, pathParts[1]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get descriptors of all AVMStores. + * + * @return A list of all descriptors. + */ + public List getAVMStores() + { + List l = fAVMStoreDAO.getAll(); + List result = new ArrayList(); + for (AVMStore store : l) + { + result.add(store.getDescriptor()); + } + return result; + } + + /** + * Get a descriptor for an AVMStore. + * + * @param name + * The name to get. + * @return The descriptor. + */ + public AVMStoreDescriptor getAVMStore(String name) + { + AVMStore store = getAVMStoreByName(name); + if (store == null) + { + return null; + } + return store.getDescriptor(); + } + + /** + * Get all version for a given AVMStore. + * + * @param name + * The name of the AVMStore. + * @return A Set will all the version ids. + */ + public List getAVMStoreVersions(String name) + { + AVMStore store = getAVMStoreByName(name); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getVersions(); + } + + /** + * Get the set of versions between (inclusive) of the given dates. From or to may be null but not both. + * + * @param name + * The name of the AVMRepository. + * @param from + * The earliest date. + * @param to + * The latest date. + * @return The Set of version IDs. + */ + public List getAVMStoreVersions(String name, Date from, Date to) + { + AVMStore store = getAVMStoreByName(name); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getVersions(from, to); + } + + /** + * Get the indirection path for a layered node. + * + * @param version + * The version to look under. + * @param path + * The path to the node. + * @return The indirection path. + */ + public String getIndirectionPath(int version, String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getIndirectionPath(version, pathParts[1]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get the next version id for the given AVMStore. + * + * @param name + * The name of the AVMStore. + * @return The next version id. + */ + public int getLatestVersionID(String name) + { + AVMStore store = getAVMStoreByName(name); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getNextVersionID(); + } + + /** + * Get the latest extant snapshotted version id. + * + * @param name + * The store name. + */ + public int getLatestSnapshotID(String name) + { + AVMStore store = getAVMStoreByName(name); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getLastVersionID(); + } + + /** + * Get an AVMStore by name. + * + * @param name + * The name of the AVMStore. + * @return The AVMStore. + */ + private AVMStore getAVMStoreByName(String name) + { + AVMStore store = fAVMStoreDAO.getByName(name); + return store; + } + + /** + * Get a descriptor for an AVMStore root. + * + * @param version + * The version to get. + * @param name + * The name of the AVMStore. + * @return The descriptor for the root. + */ + public AVMNodeDescriptor getAVMStoreRoot(int version, String name) + { + AVMStore store = getAVMStoreByName(name); + if (store == null) + { + throw new AVMNotFoundException("Not found: " + name); + } + return store.getRoot(version); + } + + // TODO Fix this awful mess regarding cycle detection. + /** + * Lookup a node. + * + * @param version + * The version to look under. + * @param path + * The path to lookup. + * @param includeDeleted + * Whether to see DeletedNodes. + * @return A lookup object. + */ + public Lookup lookup(int version, String path, boolean includeDeleted) + { + Integer count = fLookupCount.get(); + try + { + if (count == null) + { + fLookupCount.set(1); + } + else + { + fLookupCount.set(count + 1); + } + if (fLookupCount.get() > 50) + { + throw new AVMCycleException("Cycle in lookup."); + } + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + return null; + } + return store.lookup(version, pathParts[1], false, includeDeleted); + } + finally + { + if (count == null) + { + fLookupCount.set(null); + } + } + } + + /** + * Lookup a descriptor from a directory descriptor. + * + * @param dir + * The directory descriptor. + * @param name + * The name of the child to lookup. + * @return The child's descriptor. + */ + public AVMNodeDescriptor lookup(AVMNodeDescriptor dir, String name, boolean includeDeleted) + { + fLookupCount.set(1); + try + { + AVMNode node = fAVMNodeDAO.getByID(dir.getId()); + if (node == null) + { + throw new AVMNotFoundException("Not found: " + dir.getId()); + } + if (node.getType() != AVMNodeType.LAYERED_DIRECTORY && node.getType() != AVMNodeType.PLAIN_DIRECTORY) + { + throw new AVMWrongTypeException("Not a directory."); + } + DirectoryNode dirNode = (DirectoryNode) node; + if (!can(null, dirNode, PermissionService.READ_CHILDREN, false)) + { + throw new AccessDeniedException("Not allowed to read children: " + dir); + } + return dirNode.lookupChild(dir, name, includeDeleted); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get all the paths to a particular node. + * + * @param desc + * The node descriptor. + * @return The list of version, paths. + */ + public List> getPaths(AVMNodeDescriptor desc) + { + AVMNode node = fAVMNodeDAO.getByID(desc.getId()); + if (node == null) + { + throw new AVMNotFoundException("Not found: " + desc); + } + List> paths = new ArrayList>(); + List components = new ArrayList(); + recursiveGetPaths(node, components, paths); + return paths; + } + + /** + * Get a single valid path for a node. + * + * @param desc + * The node descriptor. + * @return A version, path + */ + public Pair getAPath(AVMNodeDescriptor desc) + { + AVMNode node = fAVMNodeDAO.getByID(desc.getId()); + if (node == null) + { + throw new AVMNotFoundException("Could not find node: " + desc); + } + if (fgLogger.isDebugEnabled()) + { + fgLogger.debug("Getting A Path for: " + desc); + } + List components = new ArrayList(); + return recursiveGetAPath(node, components); + } + + /** + * Get all paths for a node reachable by HEAD. + * + * @param desc + * The node descriptor. + * @return A List of all the version, path Pairs that match. + */ + public List> getHeadPaths(AVMNodeDescriptor desc) + { + AVMNode node = fAVMNodeDAO.getByID(desc.getId()); + if (node == null) + { + throw new AVMNotFoundException("Not found: " + desc.getPath()); + } + List> paths = new ArrayList>(); + List components = new ArrayList(); + recursiveGetHeadPaths(node, components, paths); + return paths; + } + + /** + * Gets all the pass from to the given node starting from the give version root. + * + * @param version + * The version root. + * @param node + * The node to get the paths of. + * @return A list of all paths in the given version to the node. + */ + public List getVersionPaths(VersionRoot version, AVMNode node) + { + List paths = new ArrayList(); + List components = new ArrayList(); + recursiveGetVersionPaths(node, components, paths, version.getRoot(), version.getAvmStore().getName()); + return paths; + } + + /** + * Helper to get all version paths. + * + * @param node + * The current node we are examining. + * @param components + * The current path components. + * @param paths + * The list to contain found paths. + * @param root + * The root node of the version. + * @param storeName + * The name of the store. + */ + private void recursiveGetVersionPaths(AVMNode node, List components, List paths, DirectoryNode root, String storeName) + { + if (!can(null, node, PermissionService.READ_CHILDREN, false)) + { + return; + } + if (node.equals(root)) + { + paths.add(this.makePath(components, storeName)); + return; + } + List entries = fChildEntryDAO.getByChild(node); + for (ChildEntry entry : entries) + { + String name = entry.getKey().getName(); + components.add(name); + AVMNode parent = entry.getKey().getParent(); + recursiveGetVersionPaths(parent, components, paths, root, storeName); + components.remove(components.size() - 1); + } + } + + /** + * Get all paths in a particular store in the head version for a particular node. + * + * @param desc + * The node descriptor. + * @param store + * The name of the store. + * @return All matching paths. + */ + public List> getPathsInStoreHead(AVMNodeDescriptor desc, String store) + { + AVMStore st = getAVMStoreByName(store); + if (st == null) + { + throw new AVMNotFoundException("Store not found: " + store); + } + AVMNode node = fAVMNodeDAO.getByID(desc.getId()); + if (node == null) + { + throw new AVMNotFoundException("Not found: " + desc); + } + List> paths = new ArrayList>(); + List components = new ArrayList(); + recursiveGetPathsInStoreHead(node, components, paths, st.getRoot(), store); + return paths; + } + + /** + * Do the actual work. + * + * @param node + * The current node. + * @param components + * The currently accumulated path components. + * @param paths + * The list to put full paths in. + */ + private void recursiveGetPaths(AVMNode node, List components, List> paths) + { + if (!can(null, node, PermissionService.READ_CHILDREN, false)) + { + return; + } + if (node.getIsRoot()) + { + AVMStore store = fAVMStoreDAO.getByRoot(node); + if (store != null) + { + addPath(components, -1, store.getName(), paths); + } + VersionRoot vr = fVersionRootDAO.getByRoot(node); + if (vr != null) + { + addPath(components, vr.getVersionID(), vr.getAvmStore().getName(), paths); + } + return; + } + List entries = fChildEntryDAO.getByChild(node); + for (ChildEntry entry : entries) + { + String name = entry.getKey().getName(); + components.add(name); + AVMNode parent = entry.getKey().getParent(); + recursiveGetPaths(parent, components, paths); + components.remove(components.size() - 1); + } + } + + /** + * Do the work of getting one path for a node. + * + * @param node + * The node to get the path of. + * @param components + * The storage for path components. + * @return A path or null. + */ + private Pair recursiveGetAPath(AVMNode node, List components) + { + if (!can(null, node, PermissionService.READ_CHILDREN, false)) + { + return null; + } + if (node.getIsRoot()) + { + AVMStore store = fAVMStoreDAO.getByRoot(node); + if (store != null) + { + if (fgLogger.isDebugEnabled()) + { + fgLogger.debug("Found path in HEAD of: " + store.getName()); + } + return new Pair(-1, makePath(components, store.getName())); + } + VersionRoot vr = fVersionRootDAO.getByRoot(node); + if (vr != null) + { + if (fgLogger.isDebugEnabled()) + { + fgLogger.debug("Found path in version " + vr.getVersionID() + " in: " + vr.getAvmStore().getName()); + } + return new Pair(vr.getVersionID(), makePath(components, vr.getAvmStore().getName())); + } + return null; + } + List entries = fChildEntryDAO.getByChild(node); + for (ChildEntry entry : entries) + { + String name = entry.getKey().getName(); + if (fgLogger.isDebugEnabled()) + { + fgLogger.debug("Found component: " + name); + } + components.add(name); + Pair path = recursiveGetAPath(AVMNodeUnwrapper.Unwrap(entry.getKey().getParent()), components); + if (path != null) + { + return path; + } + components.remove(components.size() - 1); + } + return null; + } + + /** + * Do the actual work. + * + * @param node + * The current node. + * @param components + * The currently accumulated path components. + * @param paths + * The list to put full paths in. + */ + private void recursiveGetHeadPaths(AVMNode node, List components, List> paths) + { + if (!can(null, node, PermissionService.READ_CHILDREN, false)) + { + return; + } + if (node.getIsRoot()) + { + AVMStore store = fAVMStoreDAO.getByRoot(node); + if (store != null) + { + addPath(components, -1, store.getName(), paths); + return; + } + return; + } + List entries = fChildEntryDAO.getByChild(node); + for (ChildEntry entry : entries) + { + String name = entry.getKey().getName(); + components.add(name); + AVMNode parent = entry.getKey().getParent(); + recursiveGetHeadPaths(parent, components, paths); + components.remove(components.size() - 1); + } + } + + /** + * Do the actual work. + * + * @param node + * The current node. + * @param components + * The currently accumulated path components. + * @param paths + * The list to put full paths in. + */ + private void recursiveGetPathsInStoreHead(AVMNode node, List components, List> paths, DirectoryNode root, String storeName) + { + if (!can(null, node, PermissionService.READ_CHILDREN, false)) + { + return; + } + if (node.equals(root)) + { + addPath(components, -1, storeName, paths); + return; + } + List entries = fChildEntryDAO.getByChild(node); + for (ChildEntry entry : entries) + { + String name = entry.getKey().getName(); + components.add(name); + AVMNode parent = entry.getKey().getParent(); + recursiveGetHeadPaths(parent, components, paths); + components.remove(components.size() - 1); + } + } + + /** + * Add a path to the list. + * + * @param components + * The path name components. + * @param version + * The version id. + * @param storeName + * The name of the + * @param paths + * The List to add to. + */ + private void addPath(List components, int version, String storeName, List> paths) + { + paths.add(new Pair(version, makePath(components, storeName))); + } + + /** + * Alternate version. + * + * @param components + * @param storeName + * @param paths + */ + private void addPath(List components, String storeName, List paths) + { + paths.add(makePath(components, storeName)); + } + + /** + * Helper for generating paths. + * + * @param components + * The path components. + * @param storeName + * The store that the path is in. + * @return The path. + */ + private String makePath(List components, String storeName) + { + StringBuilder pathBuilder = new StringBuilder(); + pathBuilder.append(storeName); + pathBuilder.append(":"); + if (components.size() == 0) + { + pathBuilder.append("/"); + return pathBuilder.toString(); + } + for (int i = components.size() - 1; i >= 0; i--) + { + pathBuilder.append("/"); + pathBuilder.append(components.get(i)); + } + return pathBuilder.toString(); + } + + /** + * Get information about layering of a path. + * + * @param version + * The version to look under. + * @param path + * The full avm path. + * @return A LayeringDescriptor. + */ + public LayeringDescriptor getLayeringInfo(int version, String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + Lookup lookup = store.lookup(version, pathParts[1], false, true); + if (lookup == null) + { + throw new AVMNotFoundException("Path not found."); + } + if (!can(store, lookup.getCurrentNode(), PermissionService.READ_PROPERTIES, false)) + { + throw new AccessDeniedException("Not allowed to read properties: " + path); + } + return new LayeringDescriptor(!lookup.getDirectlyContained(), lookup.getAVMStore().getDescriptor(), lookup.getFinalStore().getDescriptor()); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Lookup a directory specifically. + * + * @param version + * The version to look under. + * @param path + * The path to lookup. + * @return A lookup object. + */ + public Lookup lookupDirectory(int version, String path) + { + Integer count = fLookupCount.get(); + try + { + if (count == null) + { + fLookupCount.set(1); + } + fLookupCount.set(fLookupCount.get() + 1); + if (fLookupCount.get() > 50) + { + throw new AVMCycleException("Cycle in lookup."); + } + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + return null; + } + return store.lookupDirectory(version, pathParts[1], false); + } + finally + { + if (count == null) + { + fLookupCount.set(null); + } + } + } + + /** + * Utility to split a path, foo:bar/baz into its repository and path parts. + * + * @param path + * The fully qualified path. + * @return The repository name and the repository path. + */ + private String[] SplitPath(String path) + { + String[] pathParts = path.split(":"); + if (pathParts.length != 2) + { + throw new AVMException("Invalid path: " + path); + } + return pathParts; + } + + /** + * Make a directory into a primary indirection. + * + * @param path + * The full path. + */ + public void makePrimary(String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.makePrimary(pathParts[1]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Change what a layered directory points at. + * + * @param path + * The full path to the layered directory. + * @param target + * The new target path. + */ + public void retargetLayeredDirectory(String path, String target) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.retargetLayeredDirectory(pathParts[1], target); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get the history chain for a node. + * + * @param desc + * The node to get history of. + * @param count + * The maximum number of ancestors to traverse. Negative means all. + * @return A List of ancestors. + */ + public List getHistory(AVMNodeDescriptor desc, int count) + { + AVMNode node = fAVMNodeDAO.getByID(desc.getId()); + if (node == null) + { + throw new AVMNotFoundException("Not found."); + } + if (!can(null, node, PermissionService.READ_PROPERTIES, false)) + { + throw new AccessDeniedException("Not allowed to read properties: " + desc); + } + if (count < 0) + { + count = Integer.MAX_VALUE; + } + List history = new ArrayList(); + for (int i = 0; i < count; i++) + { + node = node.getAncestor(); + if (node == null) + { + break; + } + if (!can(null, node, PermissionService.READ_PROPERTIES, false)) + { + break; + } + history.add(node.getDescriptor("UNKNOWN", "UNKNOWN", "UNKNOWN", -1)); + } + return history; + } + + /** + * Set the opacity of a layered directory. An opaque directory hides the things it points to via indirection. + * + * @param path + * The path to the layered directory. + * @param opacity + * True is opaque; false is not. + */ + public void setOpacity(String path, boolean opacity) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.setOpacity(pathParts[1], opacity); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Set a property on a node. + * + * @param path + * The path to the node. + * @param name + * The name of the property. + * @param value + * The value of the property. + */ + public void setNodeProperty(String path, QName name, PropertyValue value) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.setNodeProperty(pathParts[1], name, value); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Set a collection of properties at once. + * + * @param path + * The path to the node. + * @param properties + * The Map of QNames to PropertyValues. + */ + public void setNodeProperties(String path, Map properties) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.setNodeProperties(pathParts[1], properties); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get a property by name for a node. + * + * @param version + * The version to look under. + * @param path + * The path to the node. + * @param name + * The name of the property. + * @return The PropertyValue or null if it does not exist. + */ + public PropertyValue getNodeProperty(int version, String path, QName name) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getNodeProperty(version, pathParts[1], name); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get a Map of all the properties of a node. + * + * @param version + * The version to look under. + * @param path + * The path to the node. + * @return A Map of QNames to PropertyValues. + */ + public Map getNodeProperties(int version, String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getNodeProperties(version, pathParts[1]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Delete a single property from a node. + * + * @param path + * The path to the node. + * @param name + * The name of the property. + */ + public void deleteNodeProperty(String path, QName name) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.deleteNodeProperty(pathParts[1], name); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Delete all properties on a node. + * + * @param path + * The path to the node. + */ + public void deleteNodeProperties(String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.deleteNodeProperties(pathParts[1]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Set a property on a store. Overwrites if property exists. + * + * @param store + * The AVMStore. + * @param name + * The QName. + * @param value + * The PropertyValue to set. + */ + public void setStoreProperty(String store, QName name, PropertyValue value) + { + AVMStore st = getAVMStoreByName(store); + if (st == null) + { + throw new AVMNotFoundException("Store not found."); + } + st.setProperty(name, value); + } + + /** + * Set a group of properties on a store. Overwrites any properties that exist. + * + * @param store + * The AVMStore. + * @param props + * The properties to set. + */ + public void setStoreProperties(String store, Map props) + { + AVMStore st = getAVMStoreByName(store); + if (st == null) + { + throw new AVMNotFoundException("Store not found."); + } + st.setProperties(props); + } + + /** + * Get a property from a store. + * + * @param store + * The name of the store. + * @param name + * The property + * @return The property value or null if non-existent. + */ + public PropertyValue getStoreProperty(String store, QName name) + { + if (store == null) + { + throw new AVMBadArgumentException("Null store name."); + } + AVMStore st = getAVMStoreByName(store); + if (st == null) + { + throw new AVMNotFoundException("Store not found."); + } + return st.getProperty(name); + } + + /** + * Queries a given store for properties with keys that match a given pattern. + * + * @param store + * The name of the store. + * @param keyPattern + * The sql 'like' pattern, inserted into a QName. + * @return A Map of the matching key value pairs. + */ + @SuppressWarnings("unchecked") + public Map queryStorePropertyKey(String store, QName keyPattern) + { + AVMStore st = getAVMStoreByName(store); + if (st == null) + { + throw new AVMNotFoundException("Store not found."); + } + List matches = fAVMStorePropertyDAO.queryByKeyPattern(st, keyPattern); + Map matchesMap = new HashMap(); + for (AVMStoreProperty prop : matches) + { + matchesMap.put(prop.getQnameId(), prop.getValue()); + } + Map propertyMap = (Map) qnameDAO.convertIdMapToQNameMap(matchesMap); + return propertyMap; + } + + /** + * Queries all AVM stores for properties with keys that match a given pattern. + * + * @param keyPattern + * The sql 'like' pattern, inserted into a QName. + * @return A List of Pairs of Store name, Map.Entry. + */ + public Map> queryStoresPropertyKeys(QName keyPattern) + { + List matches = fAVMStorePropertyDAO.queryByKeyPattern(keyPattern); + Map> results = new HashMap>(); + for (AVMStoreProperty prop : matches) + { + String storeName = prop.getStore().getName(); + QName propQName = qnameDAO.getQName(prop.getQnameId()).getSecond(); + Map pairs = null; + if ((pairs = results.get(storeName)) == null) + { + pairs = new HashMap(); + results.put(storeName, pairs); + } + pairs.put(propQName, prop.getValue()); + } + return results; + } + + /** + * Get all the properties for a store. + * + * @param store + * The name of the Store. + * @return A Map of all the properties. + */ + public Map getStoreProperties(String store) + { + if (store == null) + { + throw new AVMBadArgumentException("Null store name."); + } + AVMStore st = getAVMStoreByName(store); + if (st == null) + { + throw new AVMNotFoundException("Store not found."); + } + return st.getProperties(); + } + + /** + * Delete a property from a store. + * + * @param store + * The name of the store. + * @param name + * The name of the property. + */ + public void deleteStoreProperty(String store, QName name) + { + AVMStore st = getAVMStoreByName(store); + if (st == null) + { + throw new AVMNotFoundException("Store not found."); + } + st.deleteProperty(name); + } + + /** + * Get the common ancestor of two nodes if one exists. Unfortunately this is a quadratic problem, taking time + * proportional to the product of the lengths of the left and right history chains. + * + * @param left + * The first node. + * @param right + * The second node. + * @return The common ancestor. There are four possible results. Null means that there is no common ancestor. Left + * returned means that left is strictly an ancestor of right. Right returned means that right is strictly an + * ancestor of left. Any other non null return is the common ancestor and indicates that left and right are + * in conflict. + */ + public AVMNodeDescriptor getCommonAncestor(AVMNodeDescriptor left, AVMNodeDescriptor right) + { + AVMNode lNode = fAVMNodeDAO.getByID(left.getId()); + AVMNode rNode = fAVMNodeDAO.getByID(right.getId()); + if (lNode == null || rNode == null) + { + throw new AVMNotFoundException("Node not found."); + } + if (!can(null, lNode, PermissionService.READ_PROPERTIES, false)) + { + throw new AccessDeniedException("Not allowed to read properties: " + left); + } + if (!can(null, rNode, PermissionService.READ_PROPERTIES, false)) + { + throw new AccessDeniedException("Not allowed to read properties: " + right); + } + // TODO Short changing the permissions checking here. I'm not sure + // if that's OK. + List leftHistory = new ArrayList(); + List rightHistory = new ArrayList(); + while (lNode != null || rNode != null) + { + boolean checkRight = false; + if (lNode != null) + { + leftHistory.add(lNode); + checkRight = true; + lNode = lNode.getAncestor(); + } + boolean checkLeft = false; + if (rNode != null) + { + rightHistory.add(rNode); + checkLeft = true; + rNode = rNode.getAncestor(); + } + if (checkRight) + { + AVMNode check = leftHistory.get(leftHistory.size() - 1); + for (AVMNode node : rightHistory) + { + if (node.equals(check)) + { + return node.getDescriptor("", "", "", -1); + } + } + } + if (checkLeft) + { + AVMNode check = rightHistory.get(rightHistory.size() - 1); + for (AVMNode node : leftHistory) + { + if (node.equals(check)) + { + return node.getDescriptor("", "", "", -1); + } + } + } + } + return null; + } + + /** + * Get the ContentData for a file. + * + * @param version + * The version to look under. + * @param path + * The path to the file. + * @return The ContentData for the file. + */ + public ContentData getContentDataForRead(int version, String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + return store.getContentDataForRead(version, pathParts[1]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get the ContentData for a file for writing. + * + * @param path + * The path to the file. + * @return The ContentData object. + */ + public ContentData getContentDataForWrite(String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + ContentData result = store.getContentDataForWrite(pathParts[1]); + return result; + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Set the ContentData on a file. + * + * @param path + * The path to the file. + * @param data + * The content data to set. + */ + public void setContentData(String path, ContentData data) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.setContentData(pathParts[1], data); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get the single instance of AVMRepository. + * + * @return The single instance. + */ + public static AVMRepository GetInstance() + { + return fgInstance; + } + + public void setMetaDataFrom(String path, AVMNodeDescriptor from) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found: " + pathParts[0]); + } + AVMNode fromNode = fAVMNodeDAO.getByID(from.getId()); + if (fromNode == null) + { + throw new AVMNotFoundException("Node not found: " + from.getPath()); + } + fLookupCache.onWrite(pathParts[0]); + store.setMetaDataFrom(pathParts[1], fromNode); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Add an aspect to an AVM Node. + * + * @param path + * The path to the node. + * @param aspectName + * The name of the aspect. + */ + public void addAspect(String path, QName aspectName) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.addAspect(pathParts[1], aspectName); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get all the aspects on an AVM node. + * + * @param version + * The version to look under. + * @param path + * The path to the node. + * @return A List of the QNames of the Aspects. + */ + public Set getAspects(int version, String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getAspects(version, pathParts[1]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Remove an aspect and all associated properties from a node. + * + * @param path + * The path to the node. + * @param aspectName + * The name of the aspect. + */ + public void removeAspect(String path, QName aspectName) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.removeAspect(pathParts[1], aspectName); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Does a node have a particular aspect. + * + * @param version + * The version to look under. + * @param path + * The path to the node. + * @param aspectName + * The name of the aspect. + * @return Whether the node has the aspect. + */ + public boolean hasAspect(int version, String path, QName aspectName) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.hasAspect(version, pathParts[1], aspectName); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Set the ACL on a node. + * + * @param path + * The path to the node. + * @param acl + * The ACL to set. + */ + public void setACL(String path, DbAccessControlList acl) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + store.setACL(pathParts[1], acl); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Get the ACL on a node. + * + * @param version + * The version to look under. + * @param path + * The path to the node. + * @return The ACL. + */ + public DbAccessControlList getACL(int version, String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + return store.getACL(version, pathParts[1]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Link a node into a directory, directly. + * + * @param parentPath + * The path to the parent. + * @param name + * The name to give the node. + * @param toLink + * The node to link. + */ + public void link(String parentPath, String name, AVMNodeDescriptor toLink) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(parentPath); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + store.link(pathParts[1], name, toLink); + fLookupCache.onWrite(pathParts[0]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Update a link, directly. + * + * @param parentPath + * The path to the parent. + * @param name + * The name to give the node. + * @param toLink + * The node to link. + */ + public void updateLink(String parentPath, String name, AVMNodeDescriptor toLink) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(parentPath); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + store.updateLink(pathParts[1], name, toLink); + fLookupCache.onWrite(pathParts[0]); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * This is the danger version of link. It must be called on a copied and unsnapshotted directory. It blithely + * inserts a child without checking if a child exists with a conflicting name. + * + * @param parent + * The parent directory. + * @param name + * The name to give the child. + * @param child + * The child to link in. + */ + public void link(AVMNodeDescriptor parent, String name, AVMNodeDescriptor child) + { + AVMNode node = fAVMNodeDAO.getByID(parent.getId()); + if (!(node instanceof DirectoryNode)) + { + throw new AVMWrongTypeException("Not a Directory."); + } + DirectoryNode dir = (DirectoryNode) node; + if (!dir.getIsNew()) + { + throw new AVMException("Directory has not already been copied."); + } + if (!can(null, dir, PermissionService.ADD_CHILDREN, false)) + { + throw new AccessDeniedException("Not allowed to write: " + parent); + } + dir.link(name, child); + } + + /** + * Remove name without leaving behind a deleted node. Dangerous if used unwisely. + * + * @param path + * The path to the layered directory. + * @param name + * The name of the child. + */ + public void flatten(String path, String name) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onDelete(pathParts[0]); + Lookup lPath = store.lookup(-1, pathParts[1], true, false); + AVMNode node = lPath.getCurrentNode(); + if (node == null) + { + throw new AVMNotFoundException("Path not found."); + } + if (!(node instanceof LayeredDirectoryNode)) + { + throw new AVMWrongTypeException("Not a Layered Directory."); + } + if (!can(store, node, PermissionService.FLATTEN, lPath.getDirectlyContained())) + { + throw new AccessDeniedException("Not allowed to write in: " + path); + } + LayeredDirectoryNode dir = (LayeredDirectoryNode) node; + dir.flatten(name); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Force a copy on write. + * + * @param path + * The path to force. + */ + public AVMNodeDescriptor forceCopy(String path) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found."); + } + fLookupCache.onWrite(pathParts[0]); + // Just force a copy if needed by looking up in write mode. + Lookup lPath = store.lookup(-1, pathParts[1], true, true); + if (lPath == null) + { + throw new AVMNotFoundException("Path not found."); + } + AVMNode node = lPath.getCurrentNode(); + AVMNodeDescriptor desc = node.getDescriptor(lPath); + return desc; + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Rename a store. + * + * @param sourceName + * The original name. + * @param destName + * The new name. + * @throws AVMNotFoundException + * @throws AVMExistsException + */ + public void renameStore(String sourceName, String destName) + { + AlfrescoTransactionSupport.bindListener(fPurgeStoreTxnListener); + AlfrescoTransactionSupport.bindListener(fCreateStoreTxnListener); + AVMStore store = getAVMStoreByName(sourceName); + if (store == null) + { + throw new AVMNotFoundException("Store Not Found: " + sourceName); + } + if (getAVMStoreByName(destName) != null) + { + throw new AVMExistsException("Store Already Exists: " + destName); + } + if (!FileNameValidator.IsValid(destName)) + { + throw new AVMBadArgumentException("Bad store name: " + destName); + } + store.setName(destName); + store.createSnapshot("Rename Store", "Rename Store from " + sourceName + " to " + destName, new HashMap()); + fLookupCache.onDelete(sourceName); + fAVMStoreDAO.invalidateCache(); + fPurgeStoreTxnListener.storePurged(sourceName); + fCreateStoreTxnListener.storeCreated(destName); + } + + /** + * Revert a head path to a given version. This works by cloning the version to revert to, and then linking that new + * version into head. The reverted version will have the previous head version as ancestor. + * + * @param path + * The path to the parent directory. + * @param name + * The name of the node. + * @param toRevertTo + * The descriptor of the version to revert to. + */ + public void revert(String path, String name, AVMNodeDescriptor toRevertTo) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found: " + pathParts[0]); + } + fLookupCache.onWrite(pathParts[0]); + store.revert(pathParts[1], name, toRevertTo); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Set the GUID on a node. + * + * @param path + * @param guid + */ + public void setGuid(String path, String guid) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found:" + pathParts[0]); + } + fLookupCache.onWrite(pathParts[0]); + store.setGuid(pathParts[1], guid); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Set the encoding on a node. + * + * @param path + * @param encoding + */ + public void setEncoding(String path, String encoding) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store Not Found: " + pathParts[0]); + } + fLookupCache.onWrite(pathParts[0]); + store.setEncoding(pathParts[1], encoding); + } + finally + { + fLookupCount.set(null); + } + } + + /** + * Set the mime type on a node. + * + * @param path + * @param encoding + */ + public void setMimeType(String path, String mimeType) + { + fLookupCount.set(1); + try + { + String[] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store Not Found: " + pathParts[0]); + } + fLookupCache.onWrite(pathParts[0]); + store.setMimeType(pathParts[1], mimeType); + } + finally + { + fLookupCount.set(null); + } + } + + public List getPathsInStoreVersion(AVMNodeDescriptor desc, String store, int version) + { + AVMNode node = fAVMNodeDAO.getByID(desc.getId()); + if (node == null) + { + throw new AVMNotFoundException("Not found: " + desc); + } + List paths = new ArrayList(); + List components = new ArrayList(); + recursiveGetStoreVersionPaths(store, node, version, components, paths); + return paths; + } + + /** + * Do the actual work. + * + * @param node + * The current node. + * @param components + * The currently accumulated path components. + * @param paths + * The list to put full paths in. + */ + private void recursiveGetStoreVersionPaths(String storeName, AVMNode node, int version, List components, List paths) + { + if (!can(null, node, PermissionService.READ, false)) + { + return; + } + if (node.getIsRoot()) + { + VersionRoot versionRoot = fVersionRootDAO.getByRoot(node); + if (versionRoot.getAvmStore().getName().equals(storeName) && versionRoot.getVersionID() == version) + { + addPath(components, storeName, paths); + return; + } + return; + } + List entries = fChildEntryDAO.getByChild(node); + for (ChildEntry entry : entries) + { + String name = entry.getKey().getName(); + components.add(name); + AVMNode parent = entry.getKey().getParent(); + recursiveGetStoreVersionPaths(storeName, parent, version, components, paths); + components.remove(components.size() - 1); + } + } + + public Map getNodeProperties(AVMNodeDescriptor desc) + { + AVMNode node = fAVMNodeDAO.getByID(desc.getId()); + if (node == null) + { + throw new AVMNotFoundException("Node not found: " + desc); + } + if (!can(null, node, PermissionService.READ_PROPERTIES, false)) + { + throw new AccessDeniedException("Not allowed to read properties: " + desc); + } + QNameDAO qnameDAO = AVMDAOs.Instance().fQNameDAO; + @SuppressWarnings("unchecked") + Map converted = (Map) qnameDAO.convertIdMapToQNameMap(node.getProperties()); + return converted; + } + + public ContentData getContentDataForRead(AVMNodeDescriptor desc) + { + AVMNode node = fAVMNodeDAO.getByID(desc.getId()); + if (node == null) + { + throw new AVMNotFoundException("Node not found: " + desc); + } + if (!can(null, node, PermissionService.READ_CONTENT, false)) + { + throw new AccessDeniedException("Not allowed to read: " + desc); + } + if (node.getType() == AVMNodeType.PLAIN_FILE) + { + PlainFileNode file = (PlainFileNode) node; + return file.getContentData(); + } + throw new AVMWrongTypeException("Not a Plain File: " + desc); + } + + public Set getAspects(AVMNodeDescriptor desc) + { + AVMNode node = fAVMNodeDAO.getByID(desc.getId()); + if (node == null) + { + throw new AVMNotFoundException("Node not found: " + desc); + } + if (!can(null, node, PermissionService.READ_PROPERTIES, false)) + { + throw new AccessDeniedException("Not allowed to read properties: " + desc); + } + Set aspectIds = node.getAspects(); + // Convert to QNames + Set aspectQNames = qnameDAO.convertIdsToQNames(aspectIds); + return aspectQNames; + } + + /** + * Evaluate permission on a node. I've got a bad feeling about this... + * + * @param store + * @param node + * @param permission + * @return + */ + public boolean can(AVMStore store, AVMNode node, String permission, boolean isDirectlyContained) + { + DbAccessControlList acl = node.getAcl(); + + QName type; + if (node.getType() == AVMNodeType.PLAIN_DIRECTORY) + { + type = WCMModel.TYPE_AVM_PLAIN_FOLDER; + } + else if (node.getType() == AVMNodeType.PLAIN_FILE) + { + type = WCMModel.TYPE_AVM_PLAIN_CONTENT; + } + else if (node.getType() == AVMNodeType.LAYERED_DIRECTORY) + { + type = WCMModel.TYPE_AVM_LAYERED_FOLDER; + } + else + { + type = WCMModel.TYPE_AVM_LAYERED_CONTENT; + } + PermissionContext context = new PermissionContext(type); + + // We're doing the hand unrolling of the proxy because Hibernate/CGLIB proxies are broken + context.addDynamicAuthorityAssignment(AVMNodeUnwrapper.Unwrap(node).getBasicAttributes().getOwner(), PermissionService.OWNER_AUTHORITY); + + if ((store != null) && isDirectlyContained) + { + StoreType storeType = StoreType.getStoreType(store.getName(), store.getDescriptor(), store.getProperties()); + switch (storeType) + { + case AUTHOR: + case AUTHOR_PREVIEW: + case AUTHOR_WORKFLOW: + case AUTHOR_WORKFLOW_PREVIEW: + String storeName = store.getName(); + int first = -1; + int second = -1; + first = storeName.indexOf("--"); + if (first >= 0) + { + second = storeName.indexOf("--", first + 2); + String storeOwner; + if (second >= 0) + { + storeOwner = storeName.substring(first + 2, second); + } + else + { + storeOwner = storeName.substring(first + 2); + } + context.addDynamicAuthorityAssignment(storeOwner, PermissionService.WCM_STORE_OWNER_AUTHORITY); + } + break; + case STAGING: + case STAGING_PREVIEW: + case UNKNOWN: + case WORKFLOW: + case WORKFLOW_PREVIEW: + default: + } + + } + // Pass in node aspects + Set nodeAspectQNames = qnameDAO.convertIdsToQNames(node.getAspects()); + Set contextQNames = context.getAspects(); + contextQNames.addAll(nodeAspectQNames); + // Pass in node properties + Map nodeProperties = node.getProperties(); + Map contextProperties = new HashMap(5); + QNameDAO qnameDAO = AVMDAOs.Instance().fQNameDAO; + for (Map.Entry entry : nodeProperties.entrySet()) + { + QName qname = qnameDAO.getQName(entry.getKey()).getSecond(); + PropertyDefinition def = fDictionaryService.getProperty(qname); + if (def == null) + { + contextProperties.put(qname, entry.getValue().getValue(DataTypeDefinition.ANY)); + } + else + { + contextProperties.put(qname, entry.getValue().getValue(def.getDataType().getName())); + } + } + context.getProperties().putAll(contextProperties); + Long aclId = null; + if (acl != null) + { + aclId = acl.getId(); + } + if (store != null) + { + DbAccessControlList storeAcl = store.getStoreAcl(); + if (storeAcl != null) + { + Long storeAclID = storeAcl.getId(); + context.setStoreAcl(storeAclID); + } + } + return fPermissionService.hasPermission(aclId, context, permission) == AccessStatus.ALLOWED; + } + + public boolean can(String storeName, int version, String path, String permission) + { + Lookup lookup = AVMRepository.GetInstance().lookup(version, path, true); + if (lookup != null) + { + AVMNode node = lookup.getCurrentNode(); + AVMStore store = getAVMStoreByName(storeName); + return can(store, node, permission, lookup.getDirectlyContained()); + } + else + { + // Does not exist => allowed + return true; + } + } + + /** + * Set the acl on a store. + * + * @param storeName + * @param acl + */ + public void setStoreAcl(String storeName, DbAccessControlList acl) + { + AVMStore store = getAVMStoreByName(storeName); + if (store == null) + { + throw new AVMNotFoundException("Store not found: " + storeName); + } + store.setStoreAcl(acl); + } + + /** + * Get the ACL on a store. + * + * @param storeName + * @return + */ + public DbAccessControlList getStoreAcl(String storeName) + { + AVMStore store = getAVMStoreByName(storeName); + if (store == null) + { + throw new AVMNotFoundException("Store not found: " + storeName); + } + return store.getStoreAcl(); + } +} diff --git a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java index 2a6e9ed365..6becbca014 100644 --- a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2009 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -429,7 +429,9 @@ public class AVMStoreImpl implements AVMStore, Serializable else { // Otherwise we issue a brand new layer id. - newDir.setLayerID(fAVMRepository.issueLayerID()); + + // note: re-use generated node id as a layer id + newDir.setLayerID(newDir.getId()); } if (child != null) { diff --git a/source/java/org/alfresco/repo/avm/AvmBootstrap.java b/source/java/org/alfresco/repo/avm/AvmBootstrap.java index c83c6e4a91..96928f39e7 100644 --- a/source/java/org/alfresco/repo/avm/AvmBootstrap.java +++ b/source/java/org/alfresco/repo/avm/AvmBootstrap.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Alfresco Software Limited. + * Copyright (C) 2005-2009 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -24,7 +24,6 @@ */ package org.alfresco.repo.avm; -import java.util.ArrayList; import java.util.List; import org.alfresco.service.cmr.security.PermissionService; @@ -43,8 +42,6 @@ import org.springframework.context.ApplicationEvent; */ public class AvmBootstrap extends AbstractLifecycleBean { - private List issuers; - private AVMLockingAwareService avmLockingAwareService; private AVMRepository avmRepository; @@ -56,7 +53,6 @@ public class AvmBootstrap extends AbstractLifecycleBean public AvmBootstrap() { - issuers = new ArrayList(0); } public void setAvmLockingAwareService(AVMLockingAwareService service) @@ -79,26 +75,12 @@ public class AvmBootstrap extends AbstractLifecycleBean avmSyncService = service; } - /** - * Provide a list of {@link Issuer issuers} to bootstrap on context initialization. - * - * @see #onBootstrap(ApplicationEvent) - */ - public void setIssuers(List issuers) - { - this.issuers = issuers; - } - /** * Initialize the issuers. */ @Override protected void onBootstrap(ApplicationEvent event) { - for (Issuer issuer : issuers) - { - issuer.init(); - } avmLockingAwareService.init(); avmRepository.setPermissionService(permissionService); avmSyncService.setPermissionService(permissionService); diff --git a/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java b/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java index 1b7839e2ae..6f9c0e53b6 100644 --- a/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2009 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -49,20 +49,18 @@ public class DeletedNodeImpl extends AVMNodeImpl implements DeletedNode /** * Create a new one from scratch. - * @param id The node id. * @param store The store it's being created in. */ - public DeletedNodeImpl(long id, - AVMStore store, DbAccessControlList acl) + public DeletedNodeImpl(AVMStore store, DbAccessControlList acl) { - super(id, store); + super(store); this.setAcl(acl); } public DeletedNodeImpl(DeletedNode other, AVMStore store, Long parentAcl, ACLCopyMode mode) { - super(store.getAVMRepository().issueID(), store); + super(store); AVMDAOs.Instance().fAVMNodeDAO.save(this); AVMDAOs.Instance().fAVMNodeDAO.flush(); copyProperties(other); diff --git a/source/java/org/alfresco/repo/avm/DirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/DirectoryNodeImpl.java index 573ca020bf..29ddf6cb99 100644 --- a/source/java/org/alfresco/repo/avm/DirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/DirectoryNodeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2009 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -44,12 +44,11 @@ abstract class DirectoryNodeImpl extends AVMNodeImpl implements DirectoryNode /** * A pass through constructor. Called when a new concrete subclass * instance is created. - * @param id * @param repo */ - protected DirectoryNodeImpl(long id, AVMStore repo) + protected DirectoryNodeImpl(AVMStore repo) { - super(id, repo); + super(repo); } /** diff --git a/source/java/org/alfresco/repo/avm/FileNodeImpl.java b/source/java/org/alfresco/repo/avm/FileNodeImpl.java index af6e12ff25..dd614ade5e 100644 --- a/source/java/org/alfresco/repo/avm/FileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/FileNodeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2009 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,7 +23,6 @@ package org.alfresco.repo.avm; -import org.alfresco.repo.domain.DbAccessControlList; /** * Base class for file objects. @@ -40,11 +39,10 @@ abstract class FileNodeImpl extends AVMNodeImpl implements FileNode /** * Pass through constructor. - * @param id The newly assigned object id. * @param store The AVMStore we belong to. */ - public FileNodeImpl(long id, AVMStore store) + public FileNodeImpl(AVMStore store) { - super(id, store); + super(store); } } diff --git a/source/java/org/alfresco/repo/avm/Issuer.java b/source/java/org/alfresco/repo/avm/Issuer.java deleted file mode 100644 index ef787c70f7..0000000000 --- a/source/java/org/alfresco/repo/avm/Issuer.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" */ - -package org.alfresco.repo.avm; - -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.service.transaction.TransactionService; - -/** - * This is a helper class that knows how to issue identifiers. - * - * @author britt - */ -public class Issuer -{ - /** - * How large a block of ids to grab at a time. - */ - private static final int BLOCK_SIZE = 100; - - /** - * The next number to issue. - */ - private long fNext; - - private long fLast; - - /** - * The name of this issuer. - */ - private String fName; - - private IssuerIDDAO fIDDAO; - - private IssuerDAO fIssuerDAO; - - private TransactionService fTxnService; - - /** - * Default constructor. - */ - public Issuer() - { - fNext = 0; - fLast = 0; - } - - public void setIssuerIDDAO(IssuerIDDAO dao) - { - fIDDAO = dao; - } - - public void setIssuerDAO(IssuerDAO dao) - { - fIssuerDAO = dao; - } - - public void setTransactionService(TransactionService service) - { - fTxnService = service; - } - - public void init() - { - if (!fTxnService.isReadOnly()) - { - fTxnService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - public Object execute() - { - IssuerID issuerID = fIDDAO.get(fName); - Long id = fIssuerDAO.getIssuerValue(fName); - if (issuerID == null || id == null || id >= issuerID.getNext()) - { - if (id == null) - { - id = 0L; - } - else - { - id = id + 1L; - } - if (issuerID == null) - { - issuerID = new IssuerIDImpl(fName, id); - fIDDAO.save(issuerID); - } - else - { - issuerID.setNext(id); - } - } - return null; - } - }); - } - } - - /** - * Set the name of this issuer. For Spring. - * - * @param name - * The name to set. - */ - public void setName(String name) - { - fName = name; - } - - /** - * Issue the next number. - * - * @return A serial number. - */ - public synchronized long issue() - { - if (fNext >= fLast) - { - BlockGetter getter = new BlockGetter(); - Thread thread = new Thread(getter); - thread.start(); - try - { - thread.join(); - } - catch (InterruptedException e) - { - // Do nothing. - } - fNext = getter.fNext; - fLast = getter.fLast; - } - return fNext++; - } - - private class BlockGetter implements Runnable - { - public long fNext; - - public long fLast; - - /* - * (non-Javadoc) - * - * @see java.lang.Runnable#run() - */ - public void run() - { - fTxnService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - public Object execute() - { - IssuerID isID = fIDDAO.get(fName); - fNext = isID.getNext(); - fLast = fNext + BLOCK_SIZE; - isID.setNext(fLast); - return null; - } - }); - } - } -} diff --git a/source/java/org/alfresco/repo/avm/IssuerDAO.java b/source/java/org/alfresco/repo/avm/IssuerDAO.java deleted file mode 100644 index 9b8e819c67..0000000000 --- a/source/java/org/alfresco/repo/avm/IssuerDAO.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" */ - -package org.alfresco.repo.avm; - -/** - * DAO for Issuers. - * @author britt - */ -public interface IssuerDAO -{ - /** - * Get the Issuer value. - * @param The name of the issuer. - * @return The largest id issued by the named issuer. - */ - public Long getIssuerValue(String name); -} diff --git a/source/java/org/alfresco/repo/avm/IssuerID.java b/source/java/org/alfresco/repo/avm/IssuerID.java deleted file mode 100644 index c0e0140804..0000000000 --- a/source/java/org/alfresco/repo/avm/IssuerID.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * - */ -package org.alfresco.repo.avm; - -/** - * Trivial interface for accessing issuer ids. - * @author britt - */ -public interface IssuerID -{ - /** - * Get the name of the issuer. - * @return - */ - public String getIssuer(); - - /** - * Get the highest id. - * @return - */ - public long getNext(); - - /** - * Set the next id to be issued. - * @param next The next id to be issued. - */ - public void setNext(long next); -} diff --git a/source/java/org/alfresco/repo/avm/IssuerIDDAO.java b/source/java/org/alfresco/repo/avm/IssuerIDDAO.java deleted file mode 100644 index 179d31ca23..0000000000 --- a/source/java/org/alfresco/repo/avm/IssuerIDDAO.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * - */ -package org.alfresco.repo.avm; - -/** - * DAO interface for IssuerIDs. - * @author britt - */ -public interface IssuerIDDAO -{ - /** - * Get one by name (primary key). - * @param name - * @return - */ - public IssuerID get(String name); - - /** - * Save one. - * @param issuerID - */ - public void save(IssuerID issuerID); -} diff --git a/source/java/org/alfresco/repo/avm/IssuerIDImpl.java b/source/java/org/alfresco/repo/avm/IssuerIDImpl.java deleted file mode 100644 index bc7825a7d6..0000000000 --- a/source/java/org/alfresco/repo/avm/IssuerIDImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * - */ -package org.alfresco.repo.avm; - -/** - * Bean for issuer id tracking. - * @author britt - */ -public class IssuerIDImpl implements IssuerID -{ - private String fIssuer; - - private long fNext; - - private long fVersion; - - public IssuerIDImpl() - { - } - - public IssuerIDImpl(String issuer, long next) - { - fIssuer = issuer; - fNext = next; - } - - public void setVersion(long version) - { - fVersion = version; - } - - public long getVersion() - { - return fVersion; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.avm.IssuerID#getIssuer() - */ - public String getIssuer() - { - return fIssuer; - } - - public void setIssuer(String issuer) - { - fIssuer = issuer; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.avm.IssuerID#getNext() - */ - public long getNext() - { - return fNext; - } - - /* (non-Javadoc) - * @see org.alfresco.repo.avm.IssuerID#setNext(long) - */ - public void setNext(long next) - { - fNext = next; - } -} diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java index 8350e33762..09645de1f9 100644 --- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2009 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -95,7 +95,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public LayeredDirectoryNodeImpl(String indirection, AVMStore store, AVMNode toCopy, Long parentAcl, ACLCopyMode mode) { - super(store.getAVMRepository().issueID(), store); + super(store); fLayerID = -1; fIndirection = indirection; fIndirectionVersion = -1; @@ -159,7 +159,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public LayeredDirectoryNodeImpl(LayeredDirectoryNode other, AVMStore repos, Lookup lookup, boolean copyAll, Long parentAcl, ACLCopyMode mode) { - super(repos.getAVMRepository().issueID(), repos); + super(repos); fIndirection = other.getIndirection(); fPrimaryIndirection = other.getPrimaryIndirection(); fIndirectionVersion = -1; @@ -201,7 +201,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public LayeredDirectoryNodeImpl(PlainDirectoryNode other, AVMStore store, Lookup lPath, boolean copyContents, Long parentAcl, ACLCopyMode mode) { - super(store.getAVMRepository().issueID(), store); + super(store); fIndirection = null; fPrimaryIndirection = false; fIndirectionVersion = -1; @@ -240,7 +240,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public LayeredDirectoryNodeImpl(DirectoryNode dir, AVMStore store, Lookup srcLookup, String name, Long inheritedAcl, ACLCopyMode mode) { - super(store.getAVMRepository().issueID(), store); + super(store); fIndirection = srcLookup.getIndirectionPath() + "/" + name; fPrimaryIndirection = true; fIndirectionVersion = -1; @@ -793,7 +793,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec } if (child != null && (indirect || child.getStoreNew() == null || child.getAncestor() != null)) { - DeletedNodeImpl ghost = new DeletedNodeImpl(lPath.getAVMStore().getAVMRepository().issueID(), lPath.getAVMStore(), child.getAcl()); + DeletedNodeImpl ghost = new DeletedNodeImpl(lPath.getAVMStore(), child.getAcl()); AVMDAOs.Instance().fAVMNodeDAO.save(ghost); AVMDAOs.Instance().fAVMNodeDAO.flush(); ghost.setAncestor(child); diff --git a/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java index a48e6be5ea..fa84a33da1 100644 --- a/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2009 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -66,7 +66,7 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode */ public LayeredFileNodeImpl(LayeredFileNode other, AVMStore store, Long parentAcl, ACLCopyMode mode) { - super(store.getAVMRepository().issueID(), store); + super(store); fIndirection = other.getIndirection(); fIndirectionVersion = -1; setVersionID(other.getVersionID() + 1); @@ -88,7 +88,7 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode */ public LayeredFileNodeImpl(String indirection, AVMStore store, DbAccessControlList acl) { - super(store.getAVMRepository().issueID(), store); + super(store); fIndirection = indirection; fIndirectionVersion = -1; setVersionID(1); diff --git a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java index de683a3fdd..f160ac4206 100644 --- a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2009 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -52,7 +52,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory */ public PlainDirectoryNodeImpl(AVMStore store) { - super(store.getAVMRepository().issueID(), store); + super(store); setVersionID(1); AVMDAOs.Instance().fAVMNodeDAO.save(this); AVMDAOs.Instance().fAVMNodeDAO.flush(); @@ -74,7 +74,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory public PlainDirectoryNodeImpl(PlainDirectoryNode other, AVMStore store, Long parentAcl, ACLCopyMode mode) { - super(store.getAVMRepository().issueID(), store); + super(store); AVMDAOs.Instance().fAVMNodeDAO.save(this); for (ChildEntry child : AVMDAOs.Instance().fChildEntryDAO.getByParent(other, null)) { @@ -295,8 +295,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory AVMDAOs.Instance().fChildEntryDAO.delete(entry); if (child.getStoreNew() == null || child.getAncestor() != null) { - DeletedNodeImpl ghost = new DeletedNodeImpl(lPath.getAVMStore().getAVMRepository().issueID(), - lPath.getAVMStore(), child.getAcl()); + DeletedNodeImpl ghost = new DeletedNodeImpl(lPath.getAVMStore(), child.getAcl()); AVMDAOs.Instance().fAVMNodeDAO.save(ghost); AVMDAOs.Instance().fAVMNodeDAO.flush(); ghost.setAncestor(child); diff --git a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java index bef0408b1b..52520a10ea 100644 --- a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2009 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -79,7 +79,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode */ public PlainFileNodeImpl(AVMStore store) { - super(store.getAVMRepository().issueID(), store); + super(store); setVersionID(1); AVMDAOs.Instance().fAVMNodeDAO.save(this); AVMDAOs.Instance().fAVMNodeDAO.flush(); @@ -93,7 +93,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode public PlainFileNodeImpl(PlainFileNode other, AVMStore store, Long parentAcl, ACLCopyMode mode) { - super(store.getAVMRepository().issueID(), store); + super(store); // The null is OK because the Lookup argument is only use by // layered files. setContentData(other.getContentData(null)); @@ -123,7 +123,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode DbAccessControlList acl, int versionID, Long parentAcl, ACLCopyMode mode) { - super(store.getAVMRepository().issueID(), store); + super(store); setContentData(content); setBasicAttributes(attrs); setVersionID(versionID + 1); diff --git a/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml b/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml index 6a95720c10..194dc52a13 100644 --- a/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml +++ b/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml @@ -1,380 +1,376 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SELECT - {asp.*} - FROM - avm_store_properties asp - JOIN alf_qname qn ON (qn.id = asp.qname_id) - JOIN alf_namespace ns ON (ns.id = qn.ns_id) - WHERE - ns.uri LIKE :uri AND - qn.local_name LIKE :localName - - - - - SELECT - {asp.*} - FROM - avm_store_properties asp - JOIN alf_qname qn ON (qn.id = asp.qname_id) - JOIN alf_namespace ns ON (ns.id = qn.ns_id) - WHERE - asp.avm_store_id = :storeId AND - ns.uri LIKE :uri AND - qn.local_name LIKE :localName - - - - DELETE - FROM - avm_store_properties - WHERE - avm_store_id = :storeId AND - qname_id = :qnameId - - - - DELETE - FROM - avm_store_properties - WHERE - avm_store_id = :storeId - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + {asp.*} + FROM + avm_store_properties asp + JOIN alf_qname qn ON (qn.id = asp.qname_id) + JOIN alf_namespace ns ON (ns.id = qn.ns_id) + WHERE + ns.uri LIKE :uri AND + qn.local_name LIKE :localName + + + + + SELECT + {asp.*} + FROM + avm_store_properties asp + JOIN alf_qname qn ON (qn.id = asp.qname_id) + JOIN alf_namespace ns ON (ns.id = qn.ns_id) + WHERE + asp.avm_store_id = :storeId AND + ns.uri LIKE :uri AND + qn.local_name LIKE :localName + + + + DELETE + FROM + avm_store_properties + WHERE + avm_store_id = :storeId AND + qname_id = :qnameId + + + + DELETE + FROM + avm_store_properties + WHERE + avm_store_id = :storeId + + + diff --git a/source/java/org/alfresco/repo/avm/hibernate/IssuerDAOHibernate.java b/source/java/org/alfresco/repo/avm/hibernate/IssuerDAOHibernate.java deleted file mode 100644 index f921d50a61..0000000000 --- a/source/java/org/alfresco/repo/avm/hibernate/IssuerDAOHibernate.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" */ - -package org.alfresco.repo.avm.hibernate; - - -import org.alfresco.repo.avm.IssuerDAO; -import org.alfresco.service.cmr.avm.AVMException; -import org.springframework.orm.hibernate3.support.HibernateDaoSupport; - -/** - * DAO for Issuers. Hibernate version. - * @author britt - */ -class IssuerDAOHibernate extends HibernateDaoSupport implements - IssuerDAO -{ - /** - * Do nothing constructor. - */ - public IssuerDAOHibernate() - { - super(); - } - - /** - * Get the largest issued id for the named issuer. - * @param The name of the issuer. - * @return The value or null if the issuer is brand new. - * @throws AVMException on an invalid name. - */ - public Long getIssuerValue(String name) - { - if (name.equals("content")) - { - return (Long)getSession(). - createQuery("select max(fc.id) from FileContentImpl fc").uniqueResult(); - } - else if (name.equals("layer")) - { - return (Long)getSession(). - createQuery("select max(an.layerID) from AVMNodeImpl an").uniqueResult(); - } - else if (name.equals("node")) - { - return (Long)getSession().createQuery("select max(an.id) from AVMNodeImpl an").uniqueResult(); - } - throw new AVMException("Unknown issuer type: " + name); - } -} diff --git a/source/java/org/alfresco/repo/avm/hibernate/IssuerIDDAOHibernate.java b/source/java/org/alfresco/repo/avm/hibernate/IssuerIDDAOHibernate.java deleted file mode 100644 index 6a0a8bd4e8..0000000000 --- a/source/java/org/alfresco/repo/avm/hibernate/IssuerIDDAOHibernate.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * - */ -package org.alfresco.repo.avm.hibernate; - -import org.alfresco.repo.avm.IssuerID; -import org.alfresco.repo.avm.IssuerIDDAO; -import org.alfresco.repo.avm.IssuerIDImpl; -import org.springframework.orm.hibernate3.support.HibernateDaoSupport; - -/** - * Hibernate implementation of IssuerIDDAO - * @author britt - */ -public class IssuerIDDAOHibernate extends HibernateDaoSupport implements IssuerIDDAO -{ - /* (non-Javadoc) - * @see org.alfresco.repo.avm.IssuerIDDAO#get(java.lang.String) - */ - public IssuerID get(String name) - { - return (IssuerID)getSession().get(IssuerIDImpl.class, name); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.avm.IssuerIDDAO#save(org.alfresco.repo.avm.IssuerID) - */ - public void save(IssuerID issuerID) - { - getSession().save(issuerID); - } -}