mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged V3.4-BUG-FIX
30520: Revisited timestamp propagation (cm:modified) now that the system does this by default - Original low-level code (Hibernate optimizations) pulled back into NodeService implementation - Use case driven prompting to touch the parent node - Full indexing and policy callbacks against parent (was missing completely) - Optimizations to ensure parent node modifications are only done where required and the same transaction is used where possible - 1s accuracy limit is maintained to prevent unnecessary modifications - Enhanced tests to cover use cases where propagation is expected - ALF-10262: Timestamp propagation is enabled by default - Fixes or will fix: - ALF-10291: Test disabled: SOLRTrackingComponentTest (various) - ALF-7433: A file deleted using the web UI still appears in a NFS mount but with NULL stats - ALF-10271: Test disabled: ArchiveAndRestoreTest.testAR7889ArchiveAndRestoreMustNotModifyAuditable - ALF-10267: Test disabled: NodeServiceTest.testArchiveAndRestore Also - Found problem where cm:auditable properties could be modified directly against the cached values - Extended locking of cached entities to the AuditablePropertiesEntity git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@30598 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -100,6 +100,8 @@ public class AuditablePropertiesEntity
|
||||
return typeDef.getDefaultAspectNames().contains(ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
|
||||
private boolean locked;
|
||||
|
||||
private String auditCreator;
|
||||
private String auditCreated;
|
||||
private String auditModifier;
|
||||
@@ -114,6 +116,21 @@ public class AuditablePropertiesEntity
|
||||
*/
|
||||
public AuditablePropertiesEntity()
|
||||
{
|
||||
locked = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor to create an unlocked instance
|
||||
*/
|
||||
public AuditablePropertiesEntity(AuditablePropertiesEntity that)
|
||||
{
|
||||
locked = false;
|
||||
this.auditCreator = that.auditCreator;
|
||||
this.auditCreated = that.auditCreated;
|
||||
this.auditModifier = that.auditModifier;
|
||||
this.auditModified = that.auditModified;
|
||||
this.auditAccessed = that.auditAccessed;
|
||||
this.auditModifiedTime = that.auditModifiedTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,6 +146,22 @@ public class AuditablePropertiesEntity
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the entity against further updates to prevent accidental modification
|
||||
*/
|
||||
public synchronized void lock()
|
||||
{
|
||||
locked = true;
|
||||
}
|
||||
|
||||
private synchronized final void checkLock()
|
||||
{
|
||||
if (locked)
|
||||
{
|
||||
throw new IllegalStateException("The entity is locked against updates: " + this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param qname the property name
|
||||
* @return Returns the value of the <b>cm:auditable</b> property or <tt>null</tt>
|
||||
@@ -162,46 +195,6 @@ public class AuditablePropertiesEntity
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param qname the property name
|
||||
* @param value the property value
|
||||
* @return Returns <tt>true</tt> if the property was used
|
||||
* @deprecated Deprecated from the start, but possibly useful code
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private boolean setAuditableProperty(QName qname, Serializable value)
|
||||
{
|
||||
if (qname.equals(ContentModel.PROP_CREATOR))
|
||||
{
|
||||
auditCreator = DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||
return true;
|
||||
}
|
||||
if (qname.equals(ContentModel.PROP_MODIFIER))
|
||||
{
|
||||
auditModifier = DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||
return true;
|
||||
}
|
||||
if (qname.equals(ContentModel.PROP_CREATED))
|
||||
{
|
||||
auditCreated = DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||
return true;
|
||||
}
|
||||
if (qname.equals(ContentModel.PROP_MODIFIED))
|
||||
{
|
||||
auditModified = DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||
return true;
|
||||
}
|
||||
if (qname.equals(ContentModel.PROP_ACCESSED))
|
||||
{
|
||||
auditAccessed = DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns a <tt>Map</tt> of auditable properties
|
||||
*/
|
||||
@@ -252,6 +245,8 @@ public class AuditablePropertiesEntity
|
||||
*/
|
||||
public boolean setAuditValues(String user, Date date, boolean force, long modifiedDateToleranceMs)
|
||||
{
|
||||
checkLock();
|
||||
|
||||
// Get a user if we need
|
||||
if (user == null)
|
||||
{
|
||||
@@ -312,6 +307,8 @@ public class AuditablePropertiesEntity
|
||||
*/
|
||||
public boolean setAuditValues(String user, Date date, Map<QName, Serializable> properties)
|
||||
{
|
||||
checkLock();
|
||||
|
||||
// Need to know if anything changed
|
||||
boolean changed = false;
|
||||
|
||||
@@ -431,6 +428,7 @@ public class AuditablePropertiesEntity
|
||||
*/
|
||||
public void setAuditCreator(String auditCreator)
|
||||
{
|
||||
checkLock();
|
||||
this.auditCreator = auditCreator;
|
||||
}
|
||||
|
||||
@@ -447,6 +445,7 @@ public class AuditablePropertiesEntity
|
||||
*/
|
||||
public void setAuditCreated(String auditCreated)
|
||||
{
|
||||
checkLock();
|
||||
this.auditCreated = auditCreated;
|
||||
}
|
||||
|
||||
@@ -463,6 +462,7 @@ public class AuditablePropertiesEntity
|
||||
*/
|
||||
public void setAuditModifier(String auditModifier)
|
||||
{
|
||||
checkLock();
|
||||
this.auditModifier = auditModifier;
|
||||
}
|
||||
|
||||
@@ -492,9 +492,34 @@ public class AuditablePropertiesEntity
|
||||
*/
|
||||
public void setAuditModified(String auditModified)
|
||||
{
|
||||
checkLock();
|
||||
this.auditModified = auditModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param modifiedDateToleranceMs the number of milliseconds' to tolerate before updating the
|
||||
* modification date.
|
||||
* Setting this to 1000L (say) will mean that the modification time will not be
|
||||
* changed if the existing value is withing 1000 ms of the new time.
|
||||
* @return Returns <tt>true</tt> if there were any changes made, otherwise <tt>false</tt>
|
||||
*/
|
||||
public boolean setAuditModified(Date date, long modifiedDateToleranceMs)
|
||||
{
|
||||
checkLock();
|
||||
|
||||
long dateTime = date.getTime();
|
||||
long lastModTime = getAuditModifiedTime();
|
||||
boolean changed = false;
|
||||
if (lastModTime < 0 || (lastModTime + modifiedDateToleranceMs) < dateTime)
|
||||
{
|
||||
// The time has moved on enough
|
||||
auditModifiedTime = dateTime;
|
||||
auditModified = DefaultTypeConverter.INSTANCE.convert(String.class, date);
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* For persistance use
|
||||
*/
|
||||
@@ -508,6 +533,7 @@ public class AuditablePropertiesEntity
|
||||
*/
|
||||
public void setAuditAccessed(String auditAccessed)
|
||||
{
|
||||
checkLock();
|
||||
this.auditAccessed = auditAccessed;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user