Merged V2.2 to HEAD

7575: Permission changes for AVM.
   7577: Incorporated most of the feedback provided by Kevin C earlier today
   7578: Removed directory not removed by patch
   7579: EmailServer bug fixes
         AR-1902:  Double posts when emailing to a document
         AR-1904:  Attachments via email should be allowed on forum posts
         AR-1903:  (Partial Fix) Text attachments should be treated the same way as other attachments 
   7583: Fixed WCM-961 & WCM-962: Added confirm dialog for 'Delete All Deployment Reports' and 'Release Server' actions


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8434 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2008-03-06 14:43:55 +00:00
parent a9fac10b45
commit a49bfd311d
89 changed files with 21301 additions and 11139 deletions

View File

@@ -1,250 +1,250 @@
/*
* 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.util.Map;
import java.util.Set;
import org.alfresco.repo.domain.DbAccessControlList;
import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.namespace.QName;
/**
* The Interface for versionable objects.
* @author britt
*/
public interface AVMNode
{
/**
* Set the ancestor of this node.
* @param ancestor The ancestor to set.
*/
public void setAncestor(AVMNode ancestor);
/**
* Change the ancestor of a node.
* @param ancestor The ancestor node that should be set.
*/
public void changeAncestor(AVMNode ancestor);
/**
* Get the ancestor of this node.
* @return The ancestor of this node.
*/
public AVMNode getAncestor();
/**
* Set the merged from node.
* @param mergedFrom The merged from node.
*/
public void setMergedFrom(AVMNode mergedFrom);
/**
* Get the node this was merged from.
* @return The node this was merged from.
*/
public AVMNode getMergedFrom();
/**
* Get the version number.
* @return The version number.
*/
public int getVersionID();
/**
* Set the version number.
* @param version The version number to set.
*/
public void setVersionID(int version);
/**
* Possibly copy ourselves.
* @param lPath The Lookup for this node.
* @return A copy of ourself or null if no copy was necessary.
*/
public AVMNode copy(Lookup lPath);
/**
* Get the type of this node.
*/
public int getType();
/**
* Get the descriptor for this node.
* @param lPath The Lookup.
* @param name The name of this in the current context.
* @return The descriptor for this node.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath, String name);
/**
* Get the descriptor for this node.
* @param lPath The Lookup.
* @return The descriptor for this node.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath);
/**
* Get a node descriptor for this node.
* @param parentPath The parent path.
* @param name The name looked up as.
* @param parentIndirection The indirection of the parent.
* @param parentIndirectionVersion The indirection version of the parent.
* @return The descriptor for this node.
*/
public AVMNodeDescriptor getDescriptor(String parentPath, String name, String parentIndirection, int parentIndirectionVersion);
/**
* Get the object id.
* @return The object id.
*/
public long getId();
/**
* Get the newnews.
* @return Whether the node is new.
*/
public boolean getIsNew();
/**
* Get a string representation for debugging.
* @param lPath The Lookup.
* @return A String representation.
*/
public String toString(Lookup lPath);
/**
* Set whether this node to be a root of a AVMStore
* @param isRoot
*/
public void setIsRoot(boolean isRoot);
/**
* Get whether this node is a root of a AVMStore.
* @return Whether this node is a root.
*/
public boolean getIsRoot();
/**
* Update the modification time of this node.
*/
public void updateModTime();
/**
* Set a property.
* @param name The name of the property.
* @param value The value to set.
*/
public void setProperty(QName name, PropertyValue value);
/**
* Set a collection of properties on this node.
* @param properties The Map of QNames to PropertyValues.
*/
public void setProperties(Map<QName, PropertyValue> properties);
/**
* Get a property by name.
* @param name The name of the property to get.
* @return A PropertyValue
*/
public PropertyValue getProperty(QName name);
/**
* Get all the properties associated with this node.
* @return A Map of QNames to PropertyValues.
*/
public Map<QName, PropertyValue> getProperties();
/**
* Delete a property from this node.
* @param name The name of the property.
*/
public void deleteProperty(QName name);
/**
* Delete all properties from this node.
*/
public void deleteProperties();
/**
* Set an ACL on this node.
* @param acl The ACL to set.
*/
public void setAcl(DbAccessControlList acl);
/**
* Get the ACL on this node.
* @return The ACL on this node.
*/
public DbAccessControlList getAcl();
/**
* Set the store that we are new in.
* @param store The store we are new in.
*/
public void setStoreNew(AVMStore store);
/**
* Get the possibly null store that we're new in.
* @return The store that we're new in.
*/
public AVMStore getStoreNew();
/**
* Copy metadata from another node.
* @param other The other node.
*/
public void copyMetaDataFrom(AVMNode other);
/**
* Get the GUID associated with this version.
* @return The GUID.
*/
public String getGuid();
/**
* Set the GUID associated with this version.
* @param guid
*/
public void setGuid(String guid);
/**
* Get the Aspects that this node has.
* @return A Set of Aspects names.
*/
public Set<QName> getAspects();
/**
* Add properties to those that already exist.
* @param properties The properties to add.
*/
public void addProperties(Map<QName, PropertyValue> properties);
/**
* Get the Basic Attributes on this node.
* @return
*/
public BasicAttributes getBasicAttributes();
}
/*
* 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.util.Map;
import java.util.Set;
import org.alfresco.repo.domain.DbAccessControlList;
import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.namespace.QName;
/**
* The Interface for versionable objects.
* @author britt
*/
public interface AVMNode
{
/**
* Set the ancestor of this node.
* @param ancestor The ancestor to set.
*/
public void setAncestor(AVMNode ancestor);
/**
* Change the ancestor of a node.
* @param ancestor The ancestor node that should be set.
*/
public void changeAncestor(AVMNode ancestor);
/**
* Get the ancestor of this node.
* @return The ancestor of this node.
*/
public AVMNode getAncestor();
/**
* Set the merged from node.
* @param mergedFrom The merged from node.
*/
public void setMergedFrom(AVMNode mergedFrom);
/**
* Get the node this was merged from.
* @return The node this was merged from.
*/
public AVMNode getMergedFrom();
/**
* Get the version number.
* @return The version number.
*/
public int getVersionID();
/**
* Set the version number.
* @param version The version number to set.
*/
public void setVersionID(int version);
/**
* Possibly copy ourselves.
* @param lPath The Lookup for this node.
* @return A copy of ourself or null if no copy was necessary.
*/
public AVMNode copy(Lookup lPath);
/**
* Get the type of this node.
*/
public int getType();
/**
* Get the descriptor for this node.
* @param lPath The Lookup.
* @param name The name of this in the current context.
* @return The descriptor for this node.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath, String name);
/**
* Get the descriptor for this node.
* @param lPath The Lookup.
* @return The descriptor for this node.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath);
/**
* Get a node descriptor for this node.
* @param parentPath The parent path.
* @param name The name looked up as.
* @param parentIndirection The indirection of the parent.
* @param parentIndirectionVersion The indirection version of the parent.
* @return The descriptor for this node.
*/
public AVMNodeDescriptor getDescriptor(String parentPath, String name, String parentIndirection, int parentIndirectionVersion);
/**
* Get the object id.
* @return The object id.
*/
public long getId();
/**
* Get the newnews.
* @return Whether the node is new.
*/
public boolean getIsNew();
/**
* Get a string representation for debugging.
* @param lPath The Lookup.
* @return A String representation.
*/
public String toString(Lookup lPath);
/**
* Set whether this node to be a root of a AVMStore
* @param isRoot
*/
public void setIsRoot(boolean isRoot);
/**
* Get whether this node is a root of a AVMStore.
* @return Whether this node is a root.
*/
public boolean getIsRoot();
/**
* Update the modification time of this node.
*/
public void updateModTime();
/**
* Set a property.
* @param name The name of the property.
* @param value The value to set.
*/
public void setProperty(QName name, PropertyValue value);
/**
* Set a collection of properties on this node.
* @param properties The Map of QNames to PropertyValues.
*/
public void setProperties(Map<QName, PropertyValue> properties);
/**
* Get a property by name.
* @param name The name of the property to get.
* @return A PropertyValue
*/
public PropertyValue getProperty(QName name);
/**
* Get all the properties associated with this node.
* @return A Map of QNames to PropertyValues.
*/
public Map<QName, PropertyValue> getProperties();
/**
* Delete a property from this node.
* @param name The name of the property.
*/
public void deleteProperty(QName name);
/**
* Delete all properties from this node.
*/
public void deleteProperties();
/**
* Set an ACL on this node.
* @param acl The ACL to set.
*/
public void setAcl(DbAccessControlList acl);
/**
* Get the ACL on this node.
* @return The ACL on this node.
*/
public DbAccessControlList getAcl();
/**
* Set the store that we are new in.
* @param store The store we are new in.
*/
public void setStoreNew(AVMStore store);
/**
* Get the possibly null store that we're new in.
* @return The store that we're new in.
*/
public AVMStore getStoreNew();
/**
* Copy metadata from another node.
* @param other The other node.
*/
public void copyMetaDataFrom(AVMNode other, Long parentAcl);
/**
* Get the GUID associated with this version.
* @return The GUID.
*/
public String getGuid();
/**
* Set the GUID associated with this version.
* @param guid
*/
public void setGuid(String guid);
/**
* Get the Aspects that this node has.
* @return A Set of Aspects names.
*/
public Set<QName> getAspects();
/**
* Add properties to those that already exist.
* @param properties The properties to add.
*/
public void addProperties(Map<QName, PropertyValue> properties);
/**
* Get the Basic Attributes on this node.
* @return
*/
public BasicAttributes getBasicAttributes();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -42,6 +42,7 @@ import org.alfresco.repo.avm.util.RawServices;
import org.alfresco.repo.avm.util.SimplePath;
import org.alfresco.repo.domain.DbAccessControlList;
import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.security.permissions.ACLCopyMode;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.avm.AVMBadArgumentException;
import org.alfresco.service.cmr.avm.AVMException;
@@ -349,7 +350,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
// a LayeredDirectoryNode that gets its indirection from
// its parent.
{
newDir = new LayeredDirectoryNodeImpl((String)null, this, null);
newDir = new LayeredDirectoryNodeImpl((String)null, this, null, null, ACLCopyMode.INHERIT);
((LayeredDirectoryNodeImpl)newDir).setPrimaryIndirection(false);
((LayeredDirectoryNodeImpl)newDir).setLayerID(lPath.getTopLayer().getLayerID());
}
@@ -373,7 +374,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
newDir.getProperties().putAll(properties);
}
DbAccessControlList acl = dir.getAcl();
newDir.setAcl(acl != null ? acl.getCopy() : null);
newDir.setAcl(acl != null ? acl.getCopy(acl.getId(), ACLCopyMode.INHERIT) : null);
}
/**
@@ -397,8 +398,9 @@ public class AVMStoreImpl implements AVMStore, Serializable
{
throw new AVMExistsException("Child exists: " + name);
}
Long parentAcl = dir.getAcl() == null ? null : dir.getAcl().getId();
LayeredDirectoryNode newDir =
new LayeredDirectoryNodeImpl(srcPath, this, null);
new LayeredDirectoryNodeImpl(srcPath, this, null, parentAcl, ACLCopyMode.INHERIT);
if (lPath.isLayered())
{
// When a layered directory is made inside of a layered context,
@@ -458,7 +460,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
-1,
"UTF-8"));
DbAccessControlList acl = dir.getAcl();
file.setAcl(acl != null ? acl.getCopy() : null);
file.setAcl(acl != null ? acl.getCopy(acl.getId(), ACLCopyMode.INHERIT) : null);
ContentWriter writer = createContentWriter(AVMNodeConverter.ExtendAVMPath(path, name));
return writer.getContentOutputStream();
}
@@ -508,7 +510,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
file.getProperties().putAll(properties);
}
DbAccessControlList acl = dir.getAcl();
file.setAcl(acl != null ? acl.getCopy() : null);
file.setAcl(acl != null ? acl.getCopy(acl.getId(), ACLCopyMode.INHERIT) : null);
// Yet another flush.
AVMDAOs.Instance().fAVMNodeDAO.flush();
ContentWriter writer = createContentWriter(AVMNodeConverter.ExtendAVMPath(path, name));
@@ -541,7 +543,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
}
// TODO Reexamine decision to not check validity of srcPath.
LayeredFileNodeImpl newFile =
new LayeredFileNodeImpl(srcPath, this);
new LayeredFileNodeImpl(srcPath, this, null);
if (child != null)
{
newFile.setAncestor(child);
@@ -549,7 +551,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
dir.updateModTime();
dir.putChild(name, newFile);
DbAccessControlList acl = dir.getAcl();
newFile.setAcl(acl != null ? acl.getCopy() : null);
newFile.setAcl(acl != null ? acl.getCopy(acl.getId(), ACLCopyMode.INHERIT) : null);
// newFile.setVersionID(getNextVersionID());
}
@@ -1431,7 +1433,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
{
throw new AccessDeniedException("Not allowed to write properties: " + path);
}
node.copyMetaDataFrom(from);
node.copyMetaDataFrom(from, node.getAcl() == null ? null : node.getAcl().getInheritsFrom());
node.setGuid(GUID.generate());
}
@@ -1565,7 +1567,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
}
if (!fAVMRepository.can(lPath.getCurrentNode(), PermissionService.READ_PERMISSIONS))
{
throw new AccessDeniedException("Not allowed to read permissions: " + path);
throw new AccessDeniedException("Not allowed to read permissions: " + path + " in "+getName());
}
return lPath.getCurrentNode().getAcl();
}

View File

@@ -1,216 +1,225 @@
/*
* 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.service.cmr.avm.AVMNodeDescriptor;
/**
* Place holder for a deleted node.
* @author britt
*/
public class DeletedNodeImpl extends AVMNodeImpl implements DeletedNode
{
private static final long serialVersionUID = 7283526790174482993L;
/**
* The type of node that this is a deleted node for.
*/
private int fDeletedType;
/**
* For Hibernate's use.
*/
protected DeletedNodeImpl()
{
}
/**
* 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)
{
super(id, store);
}
public DeletedNodeImpl(DeletedNode other,
AVMStore store)
{
super(store.getAVMRepository().issueID(), store);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
copyProperties(other);
copyAspects(other);
copyACLs(other);
}
/**
* Setter.
*/
public void setDeletedType(int type)
{
fDeletedType = type;
}
/**
* Getter.
*/
public int getDeletedType()
{
return fDeletedType;
}
// TODO What happens when this is called? Does it muck anything up.
/**
* This is only called rarely.
*/
public AVMNode copy(Lookup lPath)
{
AVMNode newMe = new DeletedNodeImpl(this, lPath.getAVMStore());
newMe.setAncestor(this);
return newMe;
}
/**
* Get a descriptor.
* @param lPath The Lookup to this node's parent.
* @param name The name of this node.
* @return An AVMNodeDescriptor
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath, String name)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
if (path.endsWith("/"))
{
path = path + name;
}
else
{
path = path + "/" + name;
}
return new AVMNodeDescriptor(path,
name,
AVMNodeType.DELETED_NODE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
-1,
fDeletedType);
}
/**
* Get a descriptor.
* @param lPath The full Lookup to this.
* @return An AVMNodeDescriptor.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
return new AVMNodeDescriptor(path,
path.substring(path.lastIndexOf("/") + 1),
AVMNodeType.DELETED_NODE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
-1,
fDeletedType);
}
/**
* Get a descriptor.
* @param parentPath
* @param name
* @param parentIndirection Ignored.
* @return An AVMNodeDescriptor.
*/
public AVMNodeDescriptor getDescriptor(String parentPath, String name, String parentIndirection, int parentIndirectionVersion)
{
BasicAttributes attrs = getBasicAttributes();
String path = parentPath.endsWith("/") ? parentPath + name : parentPath + "/" + name;
return new AVMNodeDescriptor(path,
name,
AVMNodeType.DELETED_NODE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
-1,
fDeletedType);
}
/**
* Get the type of this node.
* @return The AVMNodeType of this.
*/
public int getType()
{
return AVMNodeType.DELETED_NODE;
}
/**
* Get a descriptive string representation.
* @param lPath The lookup we've been found through.
* @return A String representation.
*/
public String toString(Lookup lPath)
{
return "[DN:" + getId() + "]";
}
}
/*
* 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.domain.DbAccessControlList;
import org.alfresco.repo.security.permissions.ACLCopyMode;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
/**
* Place holder for a deleted node.
* @author britt
*/
public class DeletedNodeImpl extends AVMNodeImpl implements DeletedNode
{
private static final long serialVersionUID = 7283526790174482993L;
/**
* The type of node that this is a deleted node for.
*/
private int fDeletedType;
/**
* For Hibernate's use.
*/
protected DeletedNodeImpl()
{
}
/**
* 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)
{
super(id, store);
this.setAcl(acl);
}
public DeletedNodeImpl(DeletedNode other,
AVMStore store, Long parentAcl, ACLCopyMode mode)
{
super(store.getAVMRepository().issueID(), store);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
copyProperties(other);
copyAspects(other);
copyACLs(other, parentAcl, mode);
}
/**
* Setter.
*/
public void setDeletedType(int type)
{
fDeletedType = type;
}
/**
* Getter.
*/
public int getDeletedType()
{
return fDeletedType;
}
// TODO What happens when this is called? Does it muck anything up.
/**
* This is only called rarely.
*/
public AVMNode copy(Lookup lPath)
{
DirectoryNode dir = lPath.getCurrentNodeDirectory();
Long parentAclId = null;
if((dir != null) && (dir.getAcl() != null))
{
parentAclId = dir.getAcl().getId();
}
AVMNode newMe = new DeletedNodeImpl(this, lPath.getAVMStore(), parentAclId, ACLCopyMode.COPY);
newMe.setAncestor(this);
return newMe;
}
/**
* Get a descriptor.
* @param lPath The Lookup to this node's parent.
* @param name The name of this node.
* @return An AVMNodeDescriptor
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath, String name)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
if (path.endsWith("/"))
{
path = path + name;
}
else
{
path = path + "/" + name;
}
return new AVMNodeDescriptor(path,
name,
AVMNodeType.DELETED_NODE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
-1,
fDeletedType);
}
/**
* Get a descriptor.
* @param lPath The full Lookup to this.
* @return An AVMNodeDescriptor.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
return new AVMNodeDescriptor(path,
path.substring(path.lastIndexOf("/") + 1),
AVMNodeType.DELETED_NODE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
-1,
fDeletedType);
}
/**
* Get a descriptor.
* @param parentPath
* @param name
* @param parentIndirection Ignored.
* @return An AVMNodeDescriptor.
*/
public AVMNodeDescriptor getDescriptor(String parentPath, String name, String parentIndirection, int parentIndirectionVersion)
{
BasicAttributes attrs = getBasicAttributes();
String path = parentPath.endsWith("/") ? parentPath + name : parentPath + "/" + name;
return new AVMNodeDescriptor(path,
name,
AVMNodeType.DELETED_NODE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
-1,
fDeletedType);
}
/**
* Get the type of this node.
* @return The AVMNodeType of this.
*/
public int getType()
{
return AVMNodeType.DELETED_NODE;
}
/**
* Get a descriptive string representation.
* @param lPath The lookup we've been found through.
* @return A String representation.
*/
public String toString(Lookup lPath)
{
return "[DN:" + getId() + "]";
}
}

View File

@@ -1,79 +1,80 @@
/*
* 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.service.cmr.avm.AVMBadArgumentException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMNotFoundException;
/**
* Base class for Directories.
* @author britt
*/
abstract class DirectoryNodeImpl extends AVMNodeImpl implements DirectoryNode
{
/**
* Default constructor.
*/
protected DirectoryNodeImpl()
{
}
/**
* A pass through constructor. Called when a new concrete subclass
* instance is created.
* @param id
* @param repo
*/
protected DirectoryNodeImpl(long id, AVMStore repo)
{
super(id, repo);
}
/**
* Dangerous version of link.
* @param name The name to give the child.
* @param toLink The child to link in.
*/
public void link(String name, AVMNodeDescriptor toLink)
{
AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(toLink.getId());
if (node == null)
{
throw new AVMNotFoundException("Child node not found.");
}
if (node.getType() == AVMNodeType.LAYERED_DIRECTORY &&
!((LayeredDirectoryNode)node).getPrimaryIndirection())
{
throw new AVMBadArgumentException("Non primary layered directories cannot be linked.");
}
// Make the new ChildEntry and save.
ChildKey key = new ChildKey(this, name);
ChildEntry newChild = new ChildEntryImpl(key, node);
AVMDAOs.Instance().fChildEntryDAO.save(newChild);
AVMDAOs.Instance().fAVMNodeDAO.flush();
AVMDAOs.Instance().fChildEntryDAO.evict(newChild);
AVMDAOs.Instance().fAVMNodeDAO.evict(node);
}
}
/*
* 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.domain.DbAccessControlList;
import org.alfresco.service.cmr.avm.AVMBadArgumentException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMNotFoundException;
/**
* Base class for Directories.
* @author britt
*/
abstract class DirectoryNodeImpl extends AVMNodeImpl implements DirectoryNode
{
/**
* Default constructor.
*/
protected DirectoryNodeImpl()
{
}
/**
* A pass through constructor. Called when a new concrete subclass
* instance is created.
* @param id
* @param repo
*/
protected DirectoryNodeImpl(long id, AVMStore repo)
{
super(id, repo);
}
/**
* Dangerous version of link.
* @param name The name to give the child.
* @param toLink The child to link in.
*/
public void link(String name, AVMNodeDescriptor toLink)
{
AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(toLink.getId());
if (node == null)
{
throw new AVMNotFoundException("Child node not found.");
}
if (node.getType() == AVMNodeType.LAYERED_DIRECTORY &&
!((LayeredDirectoryNode)node).getPrimaryIndirection())
{
throw new AVMBadArgumentException("Non primary layered directories cannot be linked.");
}
// Make the new ChildEntry and save.
ChildKey key = new ChildKey(this, name);
ChildEntry newChild = new ChildEntryImpl(key, node);
AVMDAOs.Instance().fChildEntryDAO.save(newChild);
AVMDAOs.Instance().fAVMNodeDAO.flush();
AVMDAOs.Instance().fChildEntryDAO.evict(newChild);
AVMDAOs.Instance().fAVMNodeDAO.evict(node);
}
}

View File

@@ -1,48 +1,50 @@
/*
* 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;
/**
* Base class for file objects.
* @author britt
*/
abstract class FileNodeImpl extends AVMNodeImpl implements FileNode
{
/**
* Default constructor.
*/
protected FileNodeImpl()
{
}
/**
* Pass through constructor.
* @param id The newly assigned object id.
* @param store The AVMStore we belong to.
*/
public FileNodeImpl(long id, AVMStore store)
{
super(id, store);
}
}
/*
* 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.domain.DbAccessControlList;
/**
* Base class for file objects.
* @author britt
*/
abstract class FileNodeImpl extends AVMNodeImpl implements FileNode
{
/**
* Default constructor.
*/
protected FileNodeImpl()
{
}
/**
* Pass through constructor.
* @param id The newly assigned object id.
* @param store The AVMStore we belong to.
*/
public FileNodeImpl(long id, AVMStore store)
{
super(id, store);
}
}

View File

@@ -1,92 +1,92 @@
package org.alfresco.repo.avm;
/**
* Interface for Layered Directories.
* @author britt
*/
public interface LayeredDirectoryNode extends DirectoryNode, Layered
{
/**
* Does this node have a primary indirection.
* @return Whether this is a primary indirection.
*/
public boolean getPrimaryIndirection();
/**
* Set whether this has a primary indirection.
* @param has Whether this has a primary indirection.
*/
public void setPrimaryIndirection(boolean has);
/**
* Get the layer id for this node.
* @return The layer id.
*/
public long getLayerID();
/**
* Set the layer id for this node.
* @param id The id to set.
*/
public void setLayerID(long id);
/**
* Set this to be a primary indirection from the path
* passed in.
* @param path The indirection path.
*/
public void rawSetPrimary(String path);
/**
* Turn this node into a primary indirection node with the indirection
* taken from the Lookup passed in.
* Performs a copy on write.
* @param lPath
*/
public void turnPrimary(Lookup lPath);
/**
* Retarget this directory.
* @param lPath The Lookup.
* @param target The new target path.
*/
public void retarget(Lookup lPath, String target);
/**
* Make visible a node deleted in a layer.
* @param lPath The Lookup.
* @param name The name to make visible.
*/
public void uncover(Lookup lPath, String name);
/**
* Remove name without leaving behind a deleted node.
* @param name The name of the child to flatten.
*/
public void flatten(String name);
/**
* Set the indirection.
* @param indirection
*/
public void setIndirection(String indirection);
/**
* Get the indirection version.
* @return The indirection version.
*/
public Integer getIndirectionVersion();
/**
* Set the opacity of this.
* @param opacity Whether this should be opaque, i.e. not see the things it
* in its indirection.
*/
public void setOpacity(boolean opacity);
/**
* Get the opacity of this.
* @return The opacity.
*/
public boolean getOpacity();
package org.alfresco.repo.avm;
/**
* Interface for Layered Directories.
* @author britt
*/
public interface LayeredDirectoryNode extends DirectoryNode, Layered
{
/**
* Does this node have a primary indirection.
* @return Whether this is a primary indirection.
*/
public boolean getPrimaryIndirection();
/**
* Set whether this has a primary indirection.
* @param has Whether this has a primary indirection.
*/
public void setPrimaryIndirection(boolean has);
/**
* Get the layer id for this node.
* @return The layer id.
*/
public long getLayerID();
/**
* Set the layer id for this node.
* @param id The id to set.
*/
public void setLayerID(long id);
/**
* Set this to be a primary indirection from the path
* passed in.
* @param path The indirection path.
*/
public void rawSetPrimary(Lookup lPath, String path);
/**
* Turn this node into a primary indirection node with the indirection
* taken from the Lookup passed in.
* Performs a copy on write.
* @param lPath
*/
public void turnPrimary(Lookup lPath);
/**
* Retarget this directory.
* @param lPath The Lookup.
* @param target The new target path.
*/
public void retarget(Lookup lPath, String target);
/**
* Make visible a node deleted in a layer.
* @param lPath The Lookup.
* @param name The name to make visible.
*/
public void uncover(Lookup lPath, String name);
/**
* Remove name without leaving behind a deleted node.
* @param name The name of the child to flatten.
*/
public void flatten(String name);
/**
* Set the indirection.
* @param indirection
*/
public void setIndirection(String indirection);
/**
* Get the indirection version.
* @return The indirection version.
*/
public Integer getIndirectionVersion();
/**
* Set the opacity of this.
* @param opacity Whether this should be opaque, i.e. not see the things it
* in its indirection.
*/
public void setOpacity(boolean opacity);
/**
* Get the opacity of this.
* @return The opacity.
*/
public boolean getOpacity();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,338 +1,363 @@
/*
* 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.service.cmr.avm.AVMException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.repository.ContentData;
/**
* A LayeredFileNode behaves like a copy on write symlink.
* @author britt
*/
class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode
{
static final long serialVersionUID = 9208423010479156363L;
/**
* The indirection.
*/
private String fIndirection;
/**
* The indirection version.
*/
private int fIndirectionVersion;
/**
* Anonymous constructor.
*/
protected LayeredFileNodeImpl()
{
}
/**
* Basically a copy constructor. Used when a branch is created
* from a layered file.
* @param other The file to make a copy of.
* @param store The store that contains us.
*/
public LayeredFileNodeImpl(LayeredFileNode other, AVMStore store)
{
super(store.getAVMRepository().issueID(), store);
fIndirection = other.getIndirection();
fIndirectionVersion = -1;
setVersionID(other.getVersionID() + 1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
copyProperties(other);
copyAspects(other);
copyACLs(other);
}
/**
* Make a brand new layered file node.
* @param indirection The thing we point to.
* @param store The store we belong to.
*/
public LayeredFileNodeImpl(String indirection, AVMStore store)
{
super(store.getAVMRepository().issueID(), store);
fIndirection = indirection;
fIndirectionVersion = -1;
setVersionID(1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
}
/**
* Copy on write logic.
* @param lPath The path by which this was found.
*/
public AVMNode copy(Lookup lPath)
{
// LayeredFileNodes are always copied.
Lookup lookup = AVMRepository.GetInstance().lookup(-1, fIndirection, false);
if (lookup == null)
{
throw new AVMException("Unbacked layered file node.");
}
AVMNode indirect = lookup.getCurrentNode();
if (indirect.getType() != AVMNodeType.LAYERED_FILE &&
indirect.getType() != AVMNodeType.PLAIN_FILE)
{
throw new AVMException("Unbacked layered file node.");
}
// TODO This doesn't look quite right.
PlainFileNodeImpl newMe = new PlainFileNodeImpl(lPath.getAVMStore(),
getBasicAttributes(),
getContentData(lPath),
indirect.getProperties(),
indirect.getAspects(),
indirect.getAcl(),
getVersionID());
newMe.setAncestor(this);
return newMe;
}
/**
* Get the type of this node.
* @return The type.
*/
public int getType()
{
return AVMNodeType.LAYERED_FILE;
}
/**
* Get the underlying path.
* @param lookup The Lookup. (Unused here.)
* @return The underlying path.
*/
public String getUnderlying(Lookup lookup)
{
return fIndirection;
}
/**
* Get a diagnostic String representation.
* @param lPath The Lookup.
* @return A diagnostic String representation.
*/
public String toString(Lookup lPath)
{
return "[LF:" + getId() + ":" + fIndirection + "]";
}
/**
* Get the descriptor for this node.
* @param lPath The Lookup.
* @return A descriptor.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath, String name)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
if (path.endsWith("/"))
{
path = path + name;
}
else
{
path = path + "/" + name;
}
return new AVMNodeDescriptor(path,
name,
AVMNodeType.LAYERED_FILE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
getUnderlying(lPath),
getUnderlyingVersion(lPath),
false,
-1,
false,
0,
-1);
}
/**
* Get the descriptor for this node.
* @param lPath The Lookup.
* @return A descriptor.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
return new AVMNodeDescriptor(path,
path.substring(path.lastIndexOf("/") + 1),
AVMNodeType.LAYERED_FILE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
getUnderlying(lPath),
getUnderlyingVersion(lPath),
false,
-1,
false,
0,
-1);
}
/**
* Get the descriptor for this node.
* @param parentPath The parent path.
* @param name The name this was looked up with.
* @param parentIndirection The parent indirection.
* @return The descriptor.
*/
public AVMNodeDescriptor getDescriptor(String parentPath, String name, String parentIndirection, int parentIndirectionVersion)
{
BasicAttributes attrs = getBasicAttributes();
String path = parentPath.endsWith("/") ? parentPath + name : parentPath + "/" + name;
return new AVMNodeDescriptor(path,
name,
AVMNodeType.LAYERED_FILE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
fIndirection,
fIndirectionVersion,
false,
-1,
false,
0,
-1);
}
/**
* Get the indirection.
* @return The indirection.
*/
public String getIndirection()
{
return fIndirection;
}
/**
* Set the indirection.
* @param indirection
*/
public void setIndirection(String indirection)
{
fIndirection = indirection;
}
/**
* Set the ContentData for this file.
* @param contentData The value to set.
*/
public void setContentData(ContentData contentData)
{
throw new AVMException("Should not be called.");
}
// TODO The lPath argument is unnecessary.
/**
* Get the ContentData for this file.
* @return The ContentData object for this file.
*/
public ContentData getContentData(Lookup lPath)
{
Lookup lookup = lPath.getAVMStore().getAVMRepository().lookup(getUnderlyingVersion(lPath), getIndirection(), false);
if (lookup == null)
{
throw new AVMException("Invalid target.");
}
AVMNode node = lookup.getCurrentNode();
if (!(node instanceof FileNode))
{
throw new AVMException("Invalid target.");
}
FileNode file = (FileNode)node;
return file.getContentData(lookup);
}
/* (non-Javadoc)
* @see org.alfresco.repo.avm.Layered#getUnderlyingVersion(org.alfresco.repo.avm.Lookup)
*/
public int getUnderlyingVersion(Lookup lookup)
{
if (lookup.getVersion() == -1)
{
return -1;
}
return fIndirectionVersion;
}
/* (non-Javadoc)
* @see org.alfresco.repo.avm.LayeredFileNode#getIndirectionVersion()
*/
public Integer getIndirectionVersion()
{
return fIndirectionVersion;
}
/* (non-Javadoc)
* @see org.alfresco.repo.avm.LayeredFileNode#setIndirectionVersion(int)
*/
public void setIndirectionVersion(Integer version)
{
if (version == null)
{
fIndirectionVersion = -1;
}
else
{
fIndirectionVersion = version;
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.avm.LayeredFileNode#copyLiterally(org.alfresco.repo.avm.Lookup)
*/
public LayeredFileNode copyLiterally(Lookup lookup)
{
return new LayeredFileNodeImpl(this, lookup.getAVMStore());
}
}
/*
* 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.domain.DbAccessControlList;
import org.alfresco.repo.domain.hibernate.DbAccessControlListImpl;
import org.alfresco.repo.security.permissions.ACLCopyMode;
import org.alfresco.service.cmr.avm.AVMException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.repository.ContentData;
/**
* A LayeredFileNode behaves like a copy on write symlink.
*
* @author britt
*/
class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode
{
static final long serialVersionUID = 9208423010479156363L;
/**
* The indirection.
*/
private String fIndirection;
/**
* The indirection version.
*/
private int fIndirectionVersion;
/**
* Anonymous constructor.
*/
protected LayeredFileNodeImpl()
{
}
/**
* Basically a copy constructor. Used when a branch is created from a layered file.
*
* @param other
* The file to make a copy of.
* @param store
* The store that contains us.
*/
public LayeredFileNodeImpl(LayeredFileNode other, AVMStore store, Long parentAcl, ACLCopyMode mode)
{
super(store.getAVMRepository().issueID(), store);
fIndirection = other.getIndirection();
fIndirectionVersion = -1;
setVersionID(other.getVersionID() + 1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
copyProperties(other);
copyAspects(other);
copyACLs(other, parentAcl, mode);
}
/**
* Make a brand new layered file node.
*
* @param indirection
* The thing we point to.
* @param store
* The store we belong to.
*/
public LayeredFileNodeImpl(String indirection, AVMStore store, DbAccessControlList acl)
{
super(store.getAVMRepository().issueID(), store);
fIndirection = indirection;
fIndirectionVersion = -1;
setVersionID(1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
if (acl != null)
{
this.setAcl(acl);
}
else
{
if (indirection != null)
{
Lookup lookup = AVMRepository.GetInstance().lookup(-1, indirection, false);
if (lookup != null)
{
AVMNode node = lookup.getCurrentNode();
if (node.getAcl() != null)
{
setAcl(DbAccessControlListImpl.createLayeredAcl(node.getAcl().getId()));
}
else
{
setAcl(DbAccessControlListImpl.createLayeredAcl(null));
}
}
else
{
setAcl(DbAccessControlListImpl.createLayeredAcl(null));
}
}
else
{
setAcl(DbAccessControlListImpl.createLayeredAcl(null));
}
}
}
/**
* Copy on write logic.
*
* @param lPath
* The path by which this was found.
*/
public AVMNode copy(Lookup lPath)
{
// LayeredFileNodes are always copied.
Lookup lookup = AVMRepository.GetInstance().lookup(-1, fIndirection, false);
if (lookup == null)
{
throw new AVMException("Unbacked layered file node.");
}
AVMNode indirect = lookup.getCurrentNode();
if (indirect.getType() != AVMNodeType.LAYERED_FILE && indirect.getType() != AVMNodeType.PLAIN_FILE)
{
throw new AVMException("Unbacked layered file node.");
}
DirectoryNode dir = lPath.getCurrentNodeDirectory();
Long parentAclId = null;
if ((dir != null) && (dir.getAcl() != null))
{
parentAclId = dir.getAcl().getId();
}
// TODO This doesn't look quite right.
PlainFileNodeImpl newMe = new PlainFileNodeImpl(lPath.getAVMStore(), getBasicAttributes(), getContentData(lPath), indirect.getProperties(), indirect.getAspects(), indirect
.getAcl(), getVersionID(), parentAclId, ACLCopyMode.COPY);
newMe.setAncestor(this);
return newMe;
}
/**
* Get the type of this node.
*
* @return The type.
*/
public int getType()
{
return AVMNodeType.LAYERED_FILE;
}
/**
* Get the underlying path.
*
* @param lookup
* The Lookup. (Unused here.)
* @return The underlying path.
*/
public String getUnderlying(Lookup lookup)
{
return fIndirection;
}
/**
* Get a diagnostic String representation.
*
* @param lPath
* The Lookup.
* @return A diagnostic String representation.
*/
public String toString(Lookup lPath)
{
return "[LF:" + getId() + ":" + fIndirection + "]";
}
/**
* Get the descriptor for this node.
*
* @param lPath
* The Lookup.
* @return A descriptor.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath, String name)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
if (path.endsWith("/"))
{
path = path + name;
}
else
{
path = path + "/" + name;
}
return new AVMNodeDescriptor(path, name, AVMNodeType.LAYERED_FILE, attrs.getCreator(), attrs.getOwner(), attrs.getLastModifier(), attrs.getCreateDate(),
attrs.getModDate(), attrs.getAccessDate(), getId(), getGuid(), getVersionID(), getUnderlying(lPath), getUnderlyingVersion(lPath), false, -1, false, 0, -1);
}
/**
* Get the descriptor for this node.
*
* @param lPath
* The Lookup.
* @return A descriptor.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
return new AVMNodeDescriptor(path, path.substring(path.lastIndexOf("/") + 1), AVMNodeType.LAYERED_FILE, attrs.getCreator(), attrs.getOwner(), attrs.getLastModifier(),
attrs.getCreateDate(), attrs.getModDate(), attrs.getAccessDate(), getId(), getGuid(), getVersionID(), getUnderlying(lPath), getUnderlyingVersion(lPath), false, -1,
false, 0, -1);
}
/**
* Get the descriptor for this node.
*
* @param parentPath
* The parent path.
* @param name
* The name this was looked up with.
* @param parentIndirection
* The parent indirection.
* @return The descriptor.
*/
public AVMNodeDescriptor getDescriptor(String parentPath, String name, String parentIndirection, int parentIndirectionVersion)
{
BasicAttributes attrs = getBasicAttributes();
String path = parentPath.endsWith("/") ? parentPath + name : parentPath + "/" + name;
return new AVMNodeDescriptor(path, name, AVMNodeType.LAYERED_FILE, attrs.getCreator(), attrs.getOwner(), attrs.getLastModifier(), attrs.getCreateDate(),
attrs.getModDate(), attrs.getAccessDate(), getId(), getGuid(), getVersionID(), fIndirection, fIndirectionVersion, false, -1, false, 0, -1);
}
/**
* Get the indirection.
*
* @return The indirection.
*/
public String getIndirection()
{
return fIndirection;
}
/**
* Set the indirection.
*
* @param indirection
*/
public void setIndirection(String indirection)
{
fIndirection = indirection;
}
/**
* Set the ContentData for this file.
*
* @param contentData
* The value to set.
*/
public void setContentData(ContentData contentData)
{
throw new AVMException("Should not be called.");
}
// TODO The lPath argument is unnecessary.
/**
* Get the ContentData for this file.
*
* @return The ContentData object for this file.
*/
public ContentData getContentData(Lookup lPath)
{
Lookup lookup = lPath.getAVMStore().getAVMRepository().lookup(getUnderlyingVersion(lPath), getIndirection(), false);
if (lookup == null)
{
throw new AVMException("Invalid target.");
}
AVMNode node = lookup.getCurrentNode();
if (!(node instanceof FileNode))
{
throw new AVMException("Invalid target.");
}
FileNode file = (FileNode) node;
return file.getContentData(lookup);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.avm.Layered#getUnderlyingVersion(org.alfresco.repo.avm.Lookup)
*/
public int getUnderlyingVersion(Lookup lookup)
{
if (lookup.getVersion() == -1)
{
return -1;
}
return fIndirectionVersion;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.avm.LayeredFileNode#getIndirectionVersion()
*/
public Integer getIndirectionVersion()
{
return fIndirectionVersion;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.avm.LayeredFileNode#setIndirectionVersion(int)
*/
public void setIndirectionVersion(Integer version)
{
if (version == null)
{
fIndirectionVersion = -1;
}
else
{
fIndirectionVersion = version;
}
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.avm.LayeredFileNode#copyLiterally(org.alfresco.repo.avm.Lookup)
*/
public LayeredFileNode copyLiterally(Lookup lookup)
{
// As far As I can tell this not used
DirectoryNode dir = lookup.getCurrentNodeDirectory();
Long parentAclId = null;
if ((dir != null) && (dir.getAcl() != null))
{
parentAclId = dir.getAcl().getId();
}
return new LayeredFileNodeImpl(this, lookup.getAVMStore(), parentAclId, ACLCopyMode.COPY);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,352 +1,349 @@
/*
* 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.util.LinkedList;
import java.util.List;
import org.alfresco.repo.domain.DbAccessControlList;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.transaction.TransactionService;
/*
* 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.util.LinkedList;
import java.util.List;
import org.alfresco.repo.domain.DbAccessControlList;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;
/**
* This is the background thread for reaping no longer referenced nodes
* in the AVM repository. These orphans arise from purge operations.
* @author britt
*/
public class OrphanReaper
{
public void execute()
{
synchronized (this)
{
if (fRunning)
{
return;
}
fRunning = true;
}
try
{
do
{
doBatch();
if (fDone)
{
return;
}
try
{
Thread.sleep(fActiveBaseSleep);
}
catch (InterruptedException e)
{
// Do nothing.
}
} while (fActive);
}
finally
{
synchronized (this)
{
fRunning = false;
}
}
}
private Log fgLogger = LogFactory.getLog(OrphanReaper.class);
/**
* The Transaction Service
*/
private TransactionService fTransactionService;
/**
* The Session Factory
*/
private SessionFactory fSessionFactory;
/**
* Active base sleep interval.
*/
private long fActiveBaseSleep;
/**
* Batch size.
*/
private int fBatchSize;
/**
* Whether we are currently active, ie have
* work queued up.
*/
private boolean fActive;
/**
* The maximum length of the queue.
*/
private int fQueueLength;
/**
* The linked list containing ids of nodes that are purgable.
*/
private LinkedList<Long> fPurgeQueue;
private boolean fDone = false;
private boolean fRunning = false;
/**
* Create one with default parameters.
*/
public OrphanReaper()
{
fActiveBaseSleep = 1000;
fBatchSize = 50;
fQueueLength = 1000;
fActive = false;
}
// Setters for configuration.
/**
* Set the active base sleep interval.
* @param interval The interval to set in ms.
*/
public void setActiveBaseSleep(long interval)
{
fActiveBaseSleep = interval;
}
/**
* Set the batch size.
* @param size The batch size to set.
*/
public void setBatchSize(int size)
{
fBatchSize = size;
}
/**
* Set the transaction service.
* @param transactionService The service.
*/
public void setTransactionService(TransactionService transactionService)
{
fTransactionService = transactionService;
}
/**
* Set the hibernate session factory. (For Spring.)
* @param sessionFactory
*/
public void setSessionFactory(SessionFactory sessionFactory)
{
fSessionFactory = sessionFactory;
}
/**
* Set the maximum size of the queue of purgeable nodes.
* @param queueLength The max length.
*/
public void setMaxQueueLength(int queueLength)
{
fQueueLength = queueLength;
}
/**
* Start things up after configuration is complete.
*/
// public void init()
// {
// fThread = new Thread(this);
// fThread.start();
// }
/**
* Shutdown the reaper. This needs to be called when
* the application shuts down.
*/
public void shutDown()
{
fDone = true;
}
/**
* Sit in a loop, periodically querying for orphans. When orphans
* are found, unhook them in bite sized batches.
*/
// public void run()
// {
// while (!fDone)
// {
// synchronized (this)
// {
// try
// {
// wait(fActive? fActiveBaseSleep : fInactiveBaseSleep);
// }
// catch (InterruptedException ie)
// {
// // Do nothing.
// }
// doBatch();
// }
// }
// }
/**
* This is really for debugging and testing. Allows another thread to
* mark the orphan reaper busy so that it can monitor for it's being done.
*/
public void activate()
{
fActive = true;
}
/**
* See if the reaper is actively reaping.
* @return Whether this is actively reaping.
*/
public boolean isActive()
{
return fActive;
}
/**
* Do a batch of cleanup work.
*/
public void doBatch()
{
class TxnWork implements RetryingTransactionCallback<Object>
{
public Object execute()
throws Exception
{
if (fPurgeQueue == null)
{
List<AVMNode> nodes = AVMDAOs.Instance().fAVMNodeDAO.getOrphans(fQueueLength);
if (nodes.size() == 0)
{
fActive = false;
return null;
}
fPurgeQueue = new LinkedList<Long>();
for (AVMNode node : nodes)
{
fPurgeQueue.add(node.getId());
}
}
fActive = true;
for (int i = 0; i < fBatchSize; i++)
{
if (fPurgeQueue.size() == 0)
{
fPurgeQueue = null;
return null;
}
AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(fPurgeQueue.removeFirst());
// Save away the ancestor and merged from fields from this node.
HistoryLink hlink = AVMDAOs.Instance().fHistoryLinkDAO.getByDescendent(node);
AVMNode ancestor = null;
if (hlink != null)
{
ancestor = hlink.getAncestor();
AVMDAOs.Instance().fHistoryLinkDAO.delete(hlink);
}
MergeLink mlink = AVMDAOs.Instance().fMergeLinkDAO.getByTo(node);
AVMNode mergedFrom = null;
if (mlink != null)
{
mergedFrom = mlink.getMfrom();
AVMDAOs.Instance().fMergeLinkDAO.delete(mlink);
}
AVMDAOs.Instance().fAVMNodeDAO.flush();
// Get all the nodes that have this node as ancestor.
List<HistoryLink> links = AVMDAOs.Instance().fHistoryLinkDAO.getByAncestor(node);
for (HistoryLink link : links)
{
AVMNode desc = link.getDescendent();
desc.setAncestor(ancestor);
if (desc.getMergedFrom() == null)
{
desc.setMergedFrom(mergedFrom);
}
AVMDAOs.Instance().fHistoryLinkDAO.delete(link);
}
// Get all the nodes that have this node as mergedFrom
List<MergeLink> mlinks = AVMDAOs.Instance().fMergeLinkDAO.getByFrom(node);
for (MergeLink link : mlinks)
{
link.getMto().setMergedFrom(ancestor);
AVMDAOs.Instance().fMergeLinkDAO.delete(link);
}
// Get rid of all properties belonging to this node.
// AVMDAOs.Instance().fAVMNodePropertyDAO.deleteAll(node);
// Get rid of all aspects belonging to this node.
// AVMDAOs.Instance().fAVMAspectNameDAO.delete(node);
// Get rid of ACL.
DbAccessControlList acl = node.getAcl();
node.setAcl(null);
if (acl != null)
{
acl.deleteEntries();
(new HibernateTemplate(fSessionFactory)).delete(acl);
}
// Extra work for directories.
if (node.getType() == AVMNodeType.PLAIN_DIRECTORY ||
node.getType() == AVMNodeType.LAYERED_DIRECTORY)
{
// First get rid of all child entries for the node.
AVMDAOs.Instance().fChildEntryDAO.deleteByParent(node);
}
// This is not on, since content urls can be shared.
// else if (node.getType() == AVMNodeType.PLAIN_FILE)
// {
// PlainFileNode file = (PlainFileNode)node;
// String url = file.getContentData(null).getContentUrl();
// if (url != null)
// {
// RawServices.Instance().getContentStore().delete(url);
// }
// }
AVMDAOs.Instance().fAVMNodeDAO.delete(node);
}
return null;
}
}
try
{
fTransactionService.getRetryingTransactionHelper().doInTransaction(new TxnWork());
}
catch (Exception e)
{
fgLogger.error("Garbage collector error", e);
}
}
}
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;
/**
* This is the background thread for reaping no longer referenced nodes
* in the AVM repository. These orphans arise from purge operations.
* @author britt
*/
public class OrphanReaper
{
public void execute()
{
synchronized (this)
{
if (fRunning)
{
return;
}
fRunning = true;
}
try
{
do
{
doBatch();
if (fDone)
{
return;
}
try
{
Thread.sleep(fActiveBaseSleep);
}
catch (InterruptedException e)
{
// Do nothing.
}
} while (fActive);
}
finally
{
synchronized (this)
{
fRunning = false;
}
}
}
private Log fgLogger = LogFactory.getLog(OrphanReaper.class);
/**
* The Transaction Service
*/
private TransactionService fTransactionService;
/**
* The Session Factory
*/
private SessionFactory fSessionFactory;
/**
* Active base sleep interval.
*/
private long fActiveBaseSleep;
/**
* Batch size.
*/
private int fBatchSize;
/**
* Whether we are currently active, ie have
* work queued up.
*/
private boolean fActive;
/**
* The maximum length of the queue.
*/
private int fQueueLength;
/**
* The linked list containing ids of nodes that are purgable.
*/
private LinkedList<Long> fPurgeQueue;
private boolean fDone = false;
private boolean fRunning = false;
/**
* Create one with default parameters.
*/
public OrphanReaper()
{
fActiveBaseSleep = 1000;
fBatchSize = 50;
fQueueLength = 1000;
fActive = false;
}
// Setters for configuration.
/**
* Set the active base sleep interval.
* @param interval The interval to set in ms.
*/
public void setActiveBaseSleep(long interval)
{
fActiveBaseSleep = interval;
}
/**
* Set the batch size.
* @param size The batch size to set.
*/
public void setBatchSize(int size)
{
fBatchSize = size;
}
/**
* Set the transaction service.
* @param transactionService The service.
*/
public void setTransactionService(TransactionService transactionService)
{
fTransactionService = transactionService;
}
/**
* Set the hibernate session factory. (For Spring.)
* @param sessionFactory
*/
public void setSessionFactory(SessionFactory sessionFactory)
{
fSessionFactory = sessionFactory;
}
/**
* Set the maximum size of the queue of purgeable nodes.
* @param queueLength The max length.
*/
public void setMaxQueueLength(int queueLength)
{
fQueueLength = queueLength;
}
/**
* Start things up after configuration is complete.
*/
// public void init()
// {
// fThread = new Thread(this);
// fThread.start();
// }
/**
* Shutdown the reaper. This needs to be called when
* the application shuts down.
*/
public void shutDown()
{
fDone = true;
}
/**
* Sit in a loop, periodically querying for orphans. When orphans
* are found, unhook them in bite sized batches.
*/
// public void run()
// {
// while (!fDone)
// {
// synchronized (this)
// {
// try
// {
// wait(fActive? fActiveBaseSleep : fInactiveBaseSleep);
// }
// catch (InterruptedException ie)
// {
// // Do nothing.
// }
// doBatch();
// }
// }
// }
/**
* This is really for debugging and testing. Allows another thread to
* mark the orphan reaper busy so that it can monitor for it's being done.
*/
public void activate()
{
fActive = true;
}
/**
* See if the reaper is actively reaping.
* @return Whether this is actively reaping.
*/
public boolean isActive()
{
return fActive;
}
/**
* Do a batch of cleanup work.
*/
public void doBatch()
{
class TxnWork implements RetryingTransactionCallback<Object>
{
public Object execute()
throws Exception
{
if (fPurgeQueue == null)
{
List<AVMNode> nodes = AVMDAOs.Instance().fAVMNodeDAO.getOrphans(fQueueLength);
if (nodes.size() == 0)
{
fActive = false;
return null;
}
fPurgeQueue = new LinkedList<Long>();
for (AVMNode node : nodes)
{
fPurgeQueue.add(node.getId());
}
}
fActive = true;
for (int i = 0; i < fBatchSize; i++)
{
if (fPurgeQueue.size() == 0)
{
fPurgeQueue = null;
return null;
}
AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(fPurgeQueue.removeFirst());
// Save away the ancestor and merged from fields from this node.
HistoryLink hlink = AVMDAOs.Instance().fHistoryLinkDAO.getByDescendent(node);
AVMNode ancestor = null;
if (hlink != null)
{
ancestor = hlink.getAncestor();
AVMDAOs.Instance().fHistoryLinkDAO.delete(hlink);
}
MergeLink mlink = AVMDAOs.Instance().fMergeLinkDAO.getByTo(node);
AVMNode mergedFrom = null;
if (mlink != null)
{
mergedFrom = mlink.getMfrom();
AVMDAOs.Instance().fMergeLinkDAO.delete(mlink);
}
AVMDAOs.Instance().fAVMNodeDAO.flush();
// Get all the nodes that have this node as ancestor.
List<HistoryLink> links = AVMDAOs.Instance().fHistoryLinkDAO.getByAncestor(node);
for (HistoryLink link : links)
{
AVMNode desc = link.getDescendent();
desc.setAncestor(ancestor);
if (desc.getMergedFrom() == null)
{
desc.setMergedFrom(mergedFrom);
}
AVMDAOs.Instance().fHistoryLinkDAO.delete(link);
}
// Get all the nodes that have this node as mergedFrom
List<MergeLink> mlinks = AVMDAOs.Instance().fMergeLinkDAO.getByFrom(node);
for (MergeLink link : mlinks)
{
link.getMto().setMergedFrom(ancestor);
AVMDAOs.Instance().fMergeLinkDAO.delete(link);
}
// Get rid of all properties belonging to this node.
// AVMDAOs.Instance().fAVMNodePropertyDAO.deleteAll(node);
// Get rid of all aspects belonging to this node.
// AVMDAOs.Instance().fAVMAspectNameDAO.delete(node);
// Get rid of ACL.
DbAccessControlList acl = node.getAcl();
node.setAcl(null);
// Unused acls will be garbage collected
// Many acls will be shared
// Extra work for directories.
if (node.getType() == AVMNodeType.PLAIN_DIRECTORY ||
node.getType() == AVMNodeType.LAYERED_DIRECTORY)
{
// First get rid of all child entries for the node.
AVMDAOs.Instance().fChildEntryDAO.deleteByParent(node);
}
// This is not on, since content urls can be shared.
// else if (node.getType() == AVMNodeType.PLAIN_FILE)
// {
// PlainFileNode file = (PlainFileNode)node;
// String url = file.getContentData(null).getContentUrl();
// if (url != null)
// {
// RawServices.Instance().getContentStore().delete(url);
// }
// }
AVMDAOs.Instance().fAVMNodeDAO.delete(node);
}
return null;
}
}
try
{
fTransactionService.getRetryingTransactionHelper().doInTransaction(new TxnWork());
}
catch (Exception e)
{
fgLogger.error("Garbage collector error", e);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,391 +1,398 @@
/*
* 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.util.HashSet;
import java.util.List;
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.service.cmr.avm.AVMException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.namespace.QName;
/**
* A plain old file. Contains a Content object.
* @author britt
*/
class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode
{
static final long serialVersionUID = 8720376837929735294L;
/**
* The Content URL.
*/
private String fContentURL;
/**
* The Mime type.
*/
private String fMimeType;
/**
* The character encoding.
*/
private String fEncoding;
/**
* The length of the file.
*/
private long fLength;
/**
* Default constructor.
*/
protected PlainFileNodeImpl()
{
}
/**
* Make one from just an AVMStore.
* This is the constructor used when a brand new plain file is being made.
* @param store An AVMStore.
*/
public PlainFileNodeImpl(AVMStore store)
{
super(store.getAVMRepository().issueID(), store);
setVersionID(1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
}
/**
* Copy on write constructor.
* @param other The node we are being copied from.
* @param store The AVMStore.
*/
public PlainFileNodeImpl(PlainFileNode other,
AVMStore store)
{
super(store.getAVMRepository().issueID(), store);
// The null is OK because the Lookup argument is only use by
// layered files.
setContentData(other.getContentData(null));
setVersionID(other.getVersionID() + 1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
copyProperties(other);
copyAspects(other);
copyACLs(other);
}
// TODO Is there a reason for passing all these parameters instead
// of just the LayeredFileNode?
/**
* Construct a new one. This is called when a LayeredFileNode
* is copied.
* @param store
* @param attrs
* @param content
*/
public PlainFileNodeImpl(AVMStore store,
BasicAttributes attrs,
ContentData content,
Map<QName, PropertyValue> props,
Set<QName> aspects,
DbAccessControlList acl,
int versionID)
{
super(store.getAVMRepository().issueID(), store);
setContentData(content);
setBasicAttributes(attrs);
setVersionID(versionID + 1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
addProperties(props);
setAspects(new HashSet<QName>(aspects));
if (acl != null)
{
setAcl(acl.getCopy());
}
}
/**
* Copy on write logic.
* @param lPath The lookup path.
*/
public AVMNode copy(Lookup lPath)
{
PlainFileNodeImpl newMe = new PlainFileNodeImpl(this, lPath.getAVMStore());
newMe.setAncestor(this);
return newMe;
}
/**
* Get the type of this node.
* @return The type.
*/
public int getType()
{
return AVMNodeType.PLAIN_FILE;
}
/**
* Get a diagnostic string representation.
* @param lPath The Lookup.
* @return A diagnostic String representation.
*/
// @Override
public String toString(Lookup lPath)
{
return "[PF:" + getId() + "]";
}
/**
* Get the descriptor for this node.
* @param lPath The Lookup.
* @return A descriptor.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath, String name)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
if (path.endsWith("/"))
{
path = path + name;
}
else
{
path = path + "/" + name;
}
return new AVMNodeDescriptor(path,
name,
AVMNodeType.PLAIN_FILE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
getLength(),
-1);
}
/**
* Get the descriptor for this node.
* @param lPath The Lookup.
* @return A descriptor.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
return new AVMNodeDescriptor(path,
path.substring(path.lastIndexOf("/") + 1),
AVMNodeType.PLAIN_FILE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
getFileLength(),
-1);
}
/**
* Get the descriptor for this.
* @param parentPath The parent path.
* @param name The name this was looked up with.
* @param parentIndirection The parent indirection.
* @return The descriptor for this.
*/
public AVMNodeDescriptor getDescriptor(String parentPath, String name, String parentIndirection, int parentIndirectionVersion)
{
BasicAttributes attrs = getBasicAttributes();
String path = parentPath.endsWith("/") ? parentPath + name : parentPath + "/" + name;
return new AVMNodeDescriptor(path,
name,
AVMNodeType.PLAIN_FILE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
getFileLength(),
-1);
}
/**
* Get the Content URL.
* @return The content URL.
*/
public String getContentURL()
{
return fContentURL;
}
/**
* Set the Content URL.
* @param contentURL
*/
protected void setContentURL(String contentURL)
{
fContentURL = contentURL;
}
/**
* Get the character encoding.
* @return The encoding.
*/
public String getEncoding()
{
return fEncoding;
}
/**
* Set the character encoding.
* @param encoding The encoding to set.
*/
public void setEncoding(String encoding)
{
fEncoding = encoding;
}
/**
* Get the file length.
* @return The file length or null if unknown.
*/
public long getLength()
{
return fLength;
}
/**
* Get the actual file length.
* @return The actual file length;
*/
private long getFileLength()
{
if (fContentURL == null)
{
return 0L;
}
ContentReader reader = RawServices.Instance().getContentStore().getReader(fContentURL);
return reader.getSize();
}
/**
* Set the file length.
* @param length The length of the file.
*/
protected void setLength(long length)
{
fLength = length;
}
/**
* Get the mime type of the content.
* @return The Mime Type of the content.
*/
public String getMimeType()
{
return fMimeType;
}
/**
* Set the Mime Type of the content.
* @param mimeType The Mime Type to set.
*/
public void setMimeType(String mimeType)
{
fMimeType = mimeType;
}
/**
* Set the ContentData for this file.
* @param contentData The value to set.
*/
public void setContentData(ContentData contentData)
{
fContentURL = contentData.getContentUrl();
fMimeType = contentData.getMimetype();
if (fMimeType == null)
{
throw new AVMException("Null mime type.");
}
fEncoding = contentData.getEncoding();
fLength = contentData.getSize();
}
/**
* Get the ContentData for this file.
* @param lPath The lookup path used to get here. Unused here.
* @return The ContentData object for this file.
*/
public ContentData getContentData(Lookup lPath)
{
return getContentData();
}
/* (non-Javadoc)
* @see org.alfresco.repo.avm.PlainFileNode#getContentData()
*/
public ContentData getContentData()
{
return new ContentData(fContentURL, fMimeType, fLength, fEncoding);
}
}
/*
* 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.util.HashSet;
import java.util.List;
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.AVMException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.namespace.QName;
/**
* A plain old file. Contains a Content object.
* @author britt
*/
class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode
{
static final long serialVersionUID = 8720376837929735294L;
/**
* The Content URL.
*/
private String fContentURL;
/**
* The Mime type.
*/
private String fMimeType;
/**
* The character encoding.
*/
private String fEncoding;
/**
* The length of the file.
*/
private long fLength;
/**
* Default constructor.
*/
protected PlainFileNodeImpl()
{
}
/**
* Make one from just an AVMStore.
* This is the constructor used when a brand new plain file is being made.
* @param store An AVMStore.
*/
public PlainFileNodeImpl(AVMStore store)
{
super(store.getAVMRepository().issueID(), store);
setVersionID(1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
}
/**
* Copy on write constructor.
* @param other The node we are being copied from.
* @param store The AVMStore.
*/
public PlainFileNodeImpl(PlainFileNode other,
AVMStore store, Long parentAcl, ACLCopyMode mode)
{
super(store.getAVMRepository().issueID(), store);
// The null is OK because the Lookup argument is only use by
// layered files.
setContentData(other.getContentData(null));
setVersionID(other.getVersionID() + 1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
copyProperties(other);
copyAspects(other);
copyACLs(other, parentAcl, mode);
}
// TODO Is there a reason for passing all these parameters instead
// of just the LayeredFileNode?
/**
* Construct a new one. This is called when a LayeredFileNode
* is copied.
* @param store
* @param attrs
* @param content
*/
public PlainFileNodeImpl(AVMStore store,
BasicAttributes attrs,
ContentData content,
Map<QName, PropertyValue> props,
Set<QName> aspects,
DbAccessControlList acl,
int versionID, Long parentAcl, ACLCopyMode mode)
{
super(store.getAVMRepository().issueID(), store);
setContentData(content);
setBasicAttributes(attrs);
setVersionID(versionID + 1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
addProperties(props);
setAspects(new HashSet<QName>(aspects));
if (acl != null)
{
setAcl(acl.getCopy(parentAcl, mode));
}
}
/**
* Copy on write logic.
* @param lPath The lookup path.
*/
public AVMNode copy(Lookup lPath)
{
DirectoryNode dir = lPath.getCurrentNodeDirectory();
Long parentAclId = null;
if((dir != null) && (dir.getAcl() != null))
{
parentAclId = dir.getAcl().getId();
}
PlainFileNodeImpl newMe = new PlainFileNodeImpl(this, lPath.getAVMStore(), parentAclId, ACLCopyMode.COW);
newMe.setAncestor(this);
return newMe;
}
/**
* Get the type of this node.
* @return The type.
*/
public int getType()
{
return AVMNodeType.PLAIN_FILE;
}
/**
* Get a diagnostic string representation.
* @param lPath The Lookup.
* @return A diagnostic String representation.
*/
// @Override
public String toString(Lookup lPath)
{
return "[PF:" + getId() + "]";
}
/**
* Get the descriptor for this node.
* @param lPath The Lookup.
* @return A descriptor.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath, String name)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
if (path.endsWith("/"))
{
path = path + name;
}
else
{
path = path + "/" + name;
}
return new AVMNodeDescriptor(path,
name,
AVMNodeType.PLAIN_FILE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
getLength(),
-1);
}
/**
* Get the descriptor for this node.
* @param lPath The Lookup.
* @return A descriptor.
*/
public AVMNodeDescriptor getDescriptor(Lookup lPath)
{
BasicAttributes attrs = getBasicAttributes();
String path = lPath.getRepresentedPath();
return new AVMNodeDescriptor(path,
path.substring(path.lastIndexOf("/") + 1),
AVMNodeType.PLAIN_FILE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
getFileLength(),
-1);
}
/**
* Get the descriptor for this.
* @param parentPath The parent path.
* @param name The name this was looked up with.
* @param parentIndirection The parent indirection.
* @return The descriptor for this.
*/
public AVMNodeDescriptor getDescriptor(String parentPath, String name, String parentIndirection, int parentIndirectionVersion)
{
BasicAttributes attrs = getBasicAttributes();
String path = parentPath.endsWith("/") ? parentPath + name : parentPath + "/" + name;
return new AVMNodeDescriptor(path,
name,
AVMNodeType.PLAIN_FILE,
attrs.getCreator(),
attrs.getOwner(),
attrs.getLastModifier(),
attrs.getCreateDate(),
attrs.getModDate(),
attrs.getAccessDate(),
getId(),
getGuid(),
getVersionID(),
null,
-1,
false,
-1,
false,
getFileLength(),
-1);
}
/**
* Get the Content URL.
* @return The content URL.
*/
public String getContentURL()
{
return fContentURL;
}
/**
* Set the Content URL.
* @param contentURL
*/
protected void setContentURL(String contentURL)
{
fContentURL = contentURL;
}
/**
* Get the character encoding.
* @return The encoding.
*/
public String getEncoding()
{
return fEncoding;
}
/**
* Set the character encoding.
* @param encoding The encoding to set.
*/
public void setEncoding(String encoding)
{
fEncoding = encoding;
}
/**
* Get the file length.
* @return The file length or null if unknown.
*/
public long getLength()
{
return fLength;
}
/**
* Get the actual file length.
* @return The actual file length;
*/
private long getFileLength()
{
if (fContentURL == null)
{
return 0L;
}
ContentReader reader = RawServices.Instance().getContentStore().getReader(fContentURL);
return reader.getSize();
}
/**
* Set the file length.
* @param length The length of the file.
*/
protected void setLength(long length)
{
fLength = length;
}
/**
* Get the mime type of the content.
* @return The Mime Type of the content.
*/
public String getMimeType()
{
return fMimeType;
}
/**
* Set the Mime Type of the content.
* @param mimeType The Mime Type to set.
*/
public void setMimeType(String mimeType)
{
fMimeType = mimeType;
}
/**
* Set the ContentData for this file.
* @param contentData The value to set.
*/
public void setContentData(ContentData contentData)
{
fContentURL = contentData.getContentUrl();
fMimeType = contentData.getMimetype();
if (fMimeType == null)
{
throw new AVMException("Null mime type.");
}
fEncoding = contentData.getEncoding();
fLength = contentData.getSize();
}
/**
* Get the ContentData for this file.
* @param lPath The lookup path used to get here. Unused here.
* @return The ContentData object for this file.
*/
public ContentData getContentData(Lookup lPath)
{
return getContentData();
}
/* (non-Javadoc)
* @see org.alfresco.repo.avm.PlainFileNode#getContentData()
*/
public ContentData getContentData()
{
return new ContentData(fContentURL, fMimeType, fLength, fEncoding);
}
}

View File

@@ -44,7 +44,7 @@
<property name="isRoot" column="is_root" type="boolean"/>
<many-to-one name="storeNew" class="AVMStoreImpl" column="store_new_id" foreign-key="fk_avm_n_store"/>
<!-- ACL -->
<many-to-one name="acl" column="acl_id" foreign-key="fk_avm_n_acl"
<many-to-one name="acl" column="acl_id" foreign-key="fk_avm_n_acl" cascade="none"
class="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl"/>
<set name="aspects" fetch="join" lazy="false" table="avm_aspects_new" cascade="all" optimistic-lock="true">
<cache usage="read-write"/>