diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml
index c1660ca394..0dc044d49e 100644
--- a/config/alfresco/bootstrap-context.xml
+++ b/config/alfresco/bootstrap-context.xml
@@ -33,6 +33,9 @@
${system.maximumStringLength}
+
+ ${system.hibernateMaxExecutions}
+ ${db.schema.update}
diff --git a/config/alfresco/hibernate-context.xml b/config/alfresco/hibernate-context.xml
index a8525fc01a..21bcaf7d78 100644
--- a/config/alfresco/hibernate-context.xml
+++ b/config/alfresco/hibernate-context.xml
@@ -23,16 +23,31 @@
+
+
+
+
+
false
+
+
+
@@ -289,13 +304,19 @@
+
+
+
+
+
+
-
+
-
-
-
-
+
+
+
+
@@ -360,10 +381,17 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties
index 7ea4a682ee..4030e94773 100644
--- a/config/alfresco/messages/patch-service.properties
+++ b/config/alfresco/messages/patch-service.properties
@@ -2,6 +2,7 @@
patch.service.not_relevant=Not relevant to schema {0}
patch.executer.checking=Checking for patches to apply ...
patch.service.applying_patch=\tApplying patch ''{0}'' ({1}).
+patch.progress=\t\tPatch {0}% complete, estimated complete at {1}.
patch.executer.no_patches_required=No patches were required.
patch.executer.system_readonly=Patches cannot be applied to a read-only system. Possible incompatibilities may exist between the application code and the existing data.
patch.executer.not_executed =\n=== Recorded patch (not executed) === \nID: {0}\nRESULT: \n{1}\n=====================================
diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml
index 352ba2f5d0..2d5c559160 100644
--- a/config/alfresco/patch/patch-services-context.xml
+++ b/config/alfresco/patch/patch-services-context.xml
@@ -1268,6 +1268,9 @@
+
+
+
@@ -1380,6 +1383,9 @@
+
+
+
diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties
index be8003abf5..48de829525 100644
--- a/config/alfresco/repository.properties
+++ b/config/alfresco/repository.properties
@@ -74,6 +74,13 @@ system.acl.maxPermissionChecks=1000
# org.alfresco.repo.domain.schema.SchemaBootstrap for V2.1.2
system.maximumStringLength=-1
+#
+# Limit hibernate session size by trying to amalgamate events for the L2 session invalidation
+# - hibernate works as is up to this size
+# - after the limit is hit events that can be grouped invalidate the L2 cache by type and not instance
+# events may not group if there are post action listener registered (this is not the case with the default distribution)
+system.hibernateMaxExecutions=20000
+
# #################### #
# Lucene configuration #
# #################### #
diff --git a/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java b/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java
index ffc4e270e6..efdf342668 100644
--- a/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java
+++ b/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java
@@ -27,9 +27,11 @@ package org.alfresco.repo.admin.patch;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.node.integrity.IntegrityChecker;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
@@ -46,8 +48,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
- * Base implementation of the patch. This class ensures that the patch is
- * thread- and transaction-safe.
+ * Base implementation of the patch. This class ensures that the patch is thread- and transaction-safe.
*
* @author Derek Hulley
*/
@@ -56,14 +57,20 @@ public abstract class AbstractPatch implements Patch
/**
* I18N message when properties not set.
*
- *
{0} = property name
- *
{1} = patch instance
+ *
{0} = property name
+ *
{1} = patch instance
*
*/
public static final String ERR_PROPERTY_NOT_SET = "patch.general.property_not_set";
-
+ private static final String MSG_PROGRESS = "patch.progress";
+
+ private static final long RANGE_10 = 1000 * 60 * 90;
+ private static final long RANGE_5 = 1000 * 60 * 60 * 4;
+ private static final long RANGE_2 = 1000 * 60 * 90 * 10;
+
private static Log logger = LogFactory.getLog(AbstractPatch.class);
-
+ private static Log progress_logger = LogFactory.getLog(PatchExecuter.class);
+
private String id;
private int fixesFromSchema;
private int fixesToSchema;
@@ -73,7 +80,8 @@ public abstract class AbstractPatch implements Patch
private List dependsOn;
/** flag indicating if the patch was successfully applied */
private boolean applied;
- private boolean applyToTenants = true; // by default, apply to each tenant, if tenant service is enabled
+ private boolean applyToTenants;
+
/** the service to register ourselves with */
private PatchService patchService;
/** used to ensure a unique transaction per execution */
@@ -90,15 +98,22 @@ public abstract class AbstractPatch implements Patch
protected TenantDeployerService tenantDeployerService;
+ /** track completion * */
+ int percentComplete = 0;
+
+ /** start time * */
+ long startTime;
+
public AbstractPatch()
{
this.fixesFromSchema = -1;
this.fixesToSchema = -1;
this.targetSchema = -1;
this.applied = false;
+ this.applyToTenants = true; // by default, apply to each tenant, if tenant service is enabled
this.dependsOn = Collections.emptyList();
}
-
+
@Override
public String toString()
{
@@ -136,7 +151,7 @@ public abstract class AbstractPatch implements Patch
{
this.namespaceService = namespaceService;
}
-
+
/**
* Set a generally-used service
*/
@@ -167,7 +182,7 @@ public abstract class AbstractPatch implements Patch
}
/**
- * This ensures that this bean gets registered with the appropriate {@link PatchService service}.
+ * This ensures that this bean gets registered with the appropriate {@link PatchService service}.
*/
public void init()
{
@@ -184,8 +199,8 @@ public abstract class AbstractPatch implements Patch
}
/**
- *
- * @param id the unique ID of the patch. This dictates the order in which patches are applied.
+ * @param id
+ * the unique ID of the patch. This dictates the order in which patches are applied.
*/
public void setId(String id)
{
@@ -200,7 +215,8 @@ public abstract class AbstractPatch implements Patch
/**
* Set the smallest schema number that this patch may be applied to.
*
- * @param version a schema number not smaller than 0
+ * @param version
+ * a schema number not smaller than 0
*/
public void setFixesFromSchema(int version)
{
@@ -224,8 +240,8 @@ public abstract class AbstractPatch implements Patch
/**
* Set the largest schema version number that this patch may be applied to.
*
- * @param version a schema version number not smaller than the
- * {@link #setFixesFromSchema(int) from version} number.
+ * @param version
+ * a schema version number not smaller than the {@link #setFixesFromSchema(int) from version} number.
*/
public void setFixesToSchema(int version)
{
@@ -242,12 +258,11 @@ public abstract class AbstractPatch implements Patch
}
/**
- * Set the schema version that this patch attempts to take the existing schema to.
- * This is for informational purposes only, acting as an indicator of intention rather
- * than having any specific effect.
+ * Set the schema version that this patch attempts to take the existing schema to. This is for informational
+ * purposes only, acting as an indicator of intention rather than having any specific effect.
*
- * @param version a schema version number that must be greater than the
- * {@link #fixesToSchema max fix schema number}
+ * @param version
+ * a schema version number that must be greater than the {@link #fixesToSchema max fix schema number}
*/
public void setTargetSchema(int version)
{
@@ -264,7 +279,8 @@ public abstract class AbstractPatch implements Patch
}
/**
- * @param description a thorough description of the patch
+ * @param description
+ * a thorough description of the patch
*/
public void setDescription(String description)
{
@@ -275,12 +291,12 @@ public abstract class AbstractPatch implements Patch
{
return this.dependsOn;
}
-
+
/**
- * Set all the dependencies for this patch. It should not be executed
- * before all the dependencies have been applied.
+ * Set all the dependencies for this patch. It should not be executed before all the dependencies have been applied.
*
- * @param dependsOn a list of dependencies
+ * @param dependsOn
+ * a list of dependencies
*/
public void setDependsOn(List dependsOn)
{
@@ -291,12 +307,14 @@ public abstract class AbstractPatch implements Patch
{
return ((this.fixesFromSchema <= version) && (version <= fixesToSchema));
}
-
+
/**
* Performs a null check on the supplied value.
*
- * @param value value to check
- * @param name name of the property to report
+ * @param value
+ * value to check
+ * @param name
+ * name of the property to report
*/
protected final void checkPropertyNotNull(Object value, String name)
{
@@ -312,9 +330,8 @@ public abstract class AbstractPatch implements Patch
}
/**
- * Check that the schema version properties have been set appropriately.
- * Derived classes can override this method to perform their own validation provided
- * that this method is called by the derived class.
+ * Check that the schema version properties have been set appropriately. Derived classes can override this method to
+ * perform their own validation provided that this method is called by the derived class.
*/
protected void checkProperties()
{
@@ -328,12 +345,11 @@ public abstract class AbstractPatch implements Patch
checkPropertyNotNull(authenticationComponent, "authenticationComponent");
if (fixesFromSchema == -1 || fixesToSchema == -1 || targetSchema == -1)
{
- throw new AlfrescoRuntimeException(
- "Patch properties 'fixesFromSchema', 'fixesToSchema' and 'targetSchema' have not all been set on this patch: \n" +
- " patch: " + this);
+ throw new AlfrescoRuntimeException("Patch properties 'fixesFromSchema', 'fixesToSchema' and 'targetSchema' have not all been set on this patch: \n"
+ + " patch: " + this);
}
}
-
+
/**
* Sets up the transaction and ensures thread-safety.
*
@@ -344,8 +360,7 @@ public abstract class AbstractPatch implements Patch
// ensure that this has not been executed already
if (applied)
{
- throw new AlfrescoRuntimeException("The patch has already been executed: \n" +
- " patch: " + this);
+ throw new AlfrescoRuntimeException("The patch has already been executed: \n" + " patch: " + this);
}
// check properties
checkProperties();
@@ -354,9 +369,7 @@ public abstract class AbstractPatch implements Patch
{
if (logger.isDebugEnabled())
{
- logger.debug("\n" +
- "Patch will be applied: \n" +
- " patch: " + this);
+ logger.debug("\n" + "Patch will be applied: \n" + " patch: " + this);
}
AuthenticationUtil.RunAsWork authorisedPathWork = new AuthenticationUtil.RunAsWork()
{
@@ -399,16 +412,14 @@ public abstract class AbstractPatch implements Patch
return transactionService.getRetryingTransactionHelper().doInTransaction(patchWork);
}
};
+ startTime = System.currentTimeMillis();
String report = AuthenticationUtil.runAs(authorisedPathWork, AuthenticationUtil.getSystemUserName());
// the patch was successfully applied
applied = true;
// done
if (logger.isDebugEnabled())
{
- logger.debug("\n" +
- "Patch successfully applied: \n" +
- " patch: " + this + "\n" +
- " report: " + report);
+ logger.debug("\n" + "Patch successfully applied: \n" + " patch: " + this + "\n" + " report: " + report);
}
return report;
}
@@ -431,11 +442,12 @@ public abstract class AbstractPatch implements Patch
throw new PatchException(report);
}
}
-
+
/**
* Dumps the error's full message and trace to the String
*
- * @param e the throwable
+ * @param e
+ * the throwable
* @return Returns a String representative of the printStackTrace method
*/
private String makeReport(Throwable e)
@@ -454,13 +466,91 @@ public abstract class AbstractPatch implements Patch
}
/**
- * This method does the work. All transactions and thread-safety will be taken care of by this class.
- * Any exception will result in the transaction being rolled back. Integrity checks are downgraded
- * for the duration of the transaction.
+ * This method does the work. All transactions and thread-safety will be taken care of by this class. Any exception
+ * will result in the transaction being rolled back. Integrity checks are downgraded for the duration of the
+ * transaction.
*
* @return Returns the report (only success messages).
* @see #apply()
- * @throws Exception anything can be thrown. This must be used for all failures.
+ * @throws Exception
+ * anything can be thrown. This must be used for all failures.
*/
protected abstract String applyInternal() throws Exception;
+
+ /**
+ * Support to report patch completion and estimated completion time.
+ *
+ * @param estimatedTotal
+ * @param currentInteration
+ */
+ protected void reportProgress(long estimatedTotal, long currentInteration)
+ {
+ if (progress_logger.isDebugEnabled())
+ {
+ progress_logger.debug(currentInteration + "/" + estimatedTotal);
+ }
+ if (currentInteration == 0)
+ {
+ // No point reporting the start - we have already done that elsewhere ....
+ percentComplete = 0;
+ }
+ else if (currentInteration * 100l / estimatedTotal > percentComplete)
+ {
+ int previous = percentComplete;
+ percentComplete = (int) (currentInteration * 100l / estimatedTotal);
+
+ if (percentComplete < 100)
+ {
+ // conditional report
+
+ long currentTime = System.currentTimeMillis();
+ long timeSoFar = currentTime - startTime;
+ long timeRemaining = timeSoFar * (100 - percentComplete) / percentComplete;
+
+ int report = -1;
+
+ if (timeRemaining > 60000)
+ {
+ int reportInterval = getreportingInterval(timeSoFar, timeRemaining);
+
+ for (int i = previous + 1; i <= percentComplete; i++)
+ {
+ if (i % reportInterval == 0)
+ {
+ report = i;
+ }
+ }
+ if (report > 0)
+ {
+ Date end = new Date(currentTime + timeRemaining);
+
+ String msg = I18NUtil.getMessage(MSG_PROGRESS, report, end);
+ progress_logger.info(msg);
+ }
+ }
+ }
+ }
+ }
+
+ private int getreportingInterval(long soFar, long toGo)
+ {
+ long total = soFar + toGo;
+ if (total < RANGE_10)
+ {
+ return 10;
+ }
+ else if (total < RANGE_5)
+ {
+ return 5;
+ }
+ else if (total < RANGE_2)
+ {
+ return 2;
+ }
+ else
+ {
+ return 1;
+ }
+
+ }
}
diff --git a/source/java/org/alfresco/repo/admin/patch/impl/AVMPermissionsPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/AVMPermissionsPatch.java
index 5356ba7ec3..c73607b694 100644
--- a/source/java/org/alfresco/repo/admin/patch/impl/AVMPermissionsPatch.java
+++ b/source/java/org/alfresco/repo/admin/patch/impl/AVMPermissionsPatch.java
@@ -29,7 +29,10 @@ import java.util.Map;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.admin.patch.AbstractPatch;
import org.alfresco.repo.domain.AccessControlListDAO;
+import org.alfresco.repo.domain.hibernate.AclDaoComponentImpl;
import org.alfresco.repo.security.permissions.ACLType;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
/**
* Migrate permissions from the OLD format to defining, shared and layered
@@ -40,12 +43,23 @@ public class AVMPermissionsPatch extends AbstractPatch
private static final String MSG_SUCCESS = "patch.updateAvmPermissions.result";
private AccessControlListDAO accessControlListDao;
+
+ private AclDaoComponentImpl aclDaoComponent;
@Override
protected String applyInternal() throws Exception
{
+ Long toDo = aclDaoComponent.getAVMHeadNodeCount();
+ Long maxId = aclDaoComponent.getMaxAclId();
+
+ Thread progressThread = new Thread(new ProgressWatcher(toDo, maxId), "WCMPactchProgressWatcher");
+ progressThread.start();
+
Map summary = accessControlListDao.patchAcls();
+ progressThread.interrupt();
+ progressThread.join();
+
// build the result message
String msg = I18NUtil.getMessage(MSG_SUCCESS, summary.get(ACLType.DEFINING), summary.get(ACLType.LAYERED));
// done
@@ -57,4 +71,57 @@ public class AVMPermissionsPatch extends AbstractPatch
this.accessControlListDao = accessControlListDao;
}
+ public void setAclDaoComponent(AclDaoComponentImpl aclDaoComponent)
+ {
+ this.aclDaoComponent = aclDaoComponent;
+ }
+
+
+ private class ProgressWatcher implements Runnable
+ {
+ private boolean running = true;
+
+ Long toDo;
+
+ Long max;
+
+ ProgressWatcher(Long toDo, Long max)
+ {
+ this.toDo = toDo;
+ this.max = max;
+ }
+
+ public void run()
+ {
+ while (running)
+ {
+ try
+ {
+ Thread.sleep(60000);
+ }
+ catch (InterruptedException e)
+ {
+ running = false;
+ }
+
+ if (running)
+ {
+ RetryingTransactionHelper txHelper = transactionService.getRetryingTransactionHelper();
+ txHelper.setMaxRetries(1);
+ Long done = txHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+
+ public Long execute() throws Throwable
+ {
+ return aclDaoComponent.getAVMNodeCountWithNewACLS(max);
+ }
+ }, true, true);
+
+ reportProgress(toDo, done);
+ }
+ }
+ }
+
+ }
+
}
diff --git a/source/java/org/alfresco/repo/admin/patch/impl/WCMPermissionPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/WCMPermissionPatch.java
index 03e8f08b10..1867892d05 100644
--- a/source/java/org/alfresco/repo/admin/patch/impl/WCMPermissionPatch.java
+++ b/source/java/org/alfresco/repo/admin/patch/impl/WCMPermissionPatch.java
@@ -32,7 +32,10 @@ import org.alfresco.repo.admin.patch.AbstractPatch;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.avm.AVMRepository;
import org.alfresco.repo.domain.PropertyValue;
+import org.alfresco.repo.domain.hibernate.AclDaoComponentImpl;
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
@@ -43,6 +46,7 @@ import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
+import org.alfresco.service.transaction.TransactionService;
/**
* Remove ACLs on all but staging area stores On staging area stores, set ACls according to the users and roles as set
@@ -60,6 +64,8 @@ public class WCMPermissionPatch extends AbstractPatch
PermissionService permissionService;
+ AclDaoComponentImpl aclDaoComponent;
+
public void setAvmService(AVMService avmService)
{
this.avmService = avmService;
@@ -75,9 +81,20 @@ public class WCMPermissionPatch extends AbstractPatch
this.permissionService = permissionService;
}
+ public void setAclDaoComponent(AclDaoComponentImpl aclDaoComponent)
+ {
+ this.aclDaoComponent = aclDaoComponent;
+ }
+
@Override
protected String applyInternal() throws Exception
{
+ Long toDo = aclDaoComponent.getAVMHeadNodeCount();
+ Long maxId = aclDaoComponent.getMaxAclId();
+
+ Thread progressThread = new Thread(new ProgressWatcher(toDo, maxId), "WCMPactchProgressWatcher");
+ progressThread.start();
+
List stores = avmService.getStores();
for (AVMStoreDescriptor store : stores)
{
@@ -113,6 +130,9 @@ public class WCMPermissionPatch extends AbstractPatch
}
}
+ progressThread.interrupt();
+ progressThread.join();
+
// build the result message
String msg = I18NUtil.getMessage(MSG_SUCCESS);
// done
@@ -178,7 +198,7 @@ public class WCMPermissionPatch extends AbstractPatch
PropertyValue pValue = avmService.getStoreProperty(stagingAreaName, propQName);
permissionService.setPermission(dirRef.getStoreRef(), PermissionService.ALL_AUTHORITIES, PermissionService.READ, true);
-
+
if (pValue != null)
{
NodeRef webProjectNodeRef = (NodeRef) pValue.getValue(DataTypeDefinition.NODE_REF);
@@ -213,7 +233,7 @@ public class WCMPermissionPatch extends AbstractPatch
int end = name.indexOf("--", start + 1);
if (end == -1)
{
- return name.substring(start+2);
+ return name.substring(start + 2);
}
return name.substring(start + 2, end);
}
@@ -228,4 +248,50 @@ public class WCMPermissionPatch extends AbstractPatch
return name.substring(0, index);
}
+ private class ProgressWatcher implements Runnable
+ {
+ private boolean running = true;
+
+ Long toDo;
+
+ Long max;
+
+ ProgressWatcher(Long toDo, Long max)
+ {
+ this.toDo = toDo;
+ this.max = max;
+ }
+
+ public void run()
+ {
+ while (running)
+ {
+ try
+ {
+ Thread.sleep(60000);
+ }
+ catch (InterruptedException e)
+ {
+ running = false;
+ }
+
+ if (running)
+ {
+ RetryingTransactionHelper txHelper = transactionService.getRetryingTransactionHelper();
+ txHelper.setMaxRetries(1);
+ Long done = txHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+
+ public Long execute() throws Throwable
+ {
+ return aclDaoComponent.getAVMNodeCountWithNewACLS(max);
+ }
+ }, true, true);
+
+ reportProgress(toDo, done);
+ }
+ }
+ }
+
+ }
}
diff --git a/source/java/org/alfresco/repo/avm/AVMServicePermissionsTest.java b/source/java/org/alfresco/repo/avm/AVMServicePermissionsTest.java
index b41bd9fa3d..d2fe13f908 100644
--- a/source/java/org/alfresco/repo/avm/AVMServicePermissionsTest.java
+++ b/source/java/org/alfresco/repo/avm/AVMServicePermissionsTest.java
@@ -404,7 +404,7 @@ public class AVMServicePermissionsTest extends TestCase
runAs(curentUser);
}
}
-
+
public void testStoreAcls() throws Exception
{
runAs("admin");
@@ -416,74 +416,73 @@ public class AVMServicePermissionsTest extends TestCase
AVMNodeDescriptor nodeDesc = avmService.lookup(-1, storeName + ":/base");
NodeRef nodeRef = AVMNodeConverter.ToNodeRef(-1, nodeDesc.getPath());
permissionService.setPermission(nodeRef, PermissionService.ALL_AUTHORITIES, PermissionService.ALL_PERMISSIONS, true);
-
- assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
-
- permissionService.setPermission(nodeRef.getStoreRef(), "andy", PermissionService.ALL_PERMISSIONS, true);
-
- assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
-
- permissionService.deletePermission(nodeRef.getStoreRef(), "andy", PermissionService.ALL_PERMISSIONS);
-
- assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
-
- permissionService.deletePermissions(nodeRef.getStoreRef());
-
- assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
-
+
+ assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
permissionService.setPermission(nodeRef.getStoreRef(), "andy", PermissionService.ALL_PERMISSIONS, true);
- assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+
+ assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+
+ permissionService.deletePermission(nodeRef.getStoreRef(), "andy", PermissionService.ALL_PERMISSIONS);
+
+ assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+
+ permissionService.deletePermissions(nodeRef.getStoreRef());
+
+ assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+
+ permissionService.setPermission(nodeRef.getStoreRef(), "andy", PermissionService.ALL_PERMISSIONS, true);
+ assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, true));
permissionService.setPermission(nodeRef.getStoreRef(), "andy", PermissionService.READ, true);
permissionService.setPermission(nodeRef.getStoreRef(), "lemur", PermissionService.ALL_PERMISSIONS, true);
-
- assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+
+ assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
assertEquals(permissionService.getAllSetPermissions(nodeRef.getStoreRef()).size(), 3);
-
+
permissionService.clearPermission(nodeRef.getStoreRef(), "andy");
-
- assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+
+ assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
assertEquals(permissionService.getAllSetPermissions(nodeRef.getStoreRef()).size(), 1);
-
+
permissionService.clearPermission(nodeRef.getStoreRef(), "lemur");
-
- assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, false));
- assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
- assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
-
+
+ assertTrue(checkPermission("andy", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkHasPermission("andy", nodeRef, PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkPermission("lemur", storeName + ":/base", PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkHasPermission("lemur", nodeRef, PermissionService.ALL_PERMISSIONS, false));
+ assertTrue(checkPermission("admin", storeName + ":/base", PermissionService.ALL_PERMISSIONS, true));
+ assertTrue(checkHasPermission("admin", nodeRef, PermissionService.ALL_PERMISSIONS, true));
+
}
finally
{
@@ -495,11 +494,13 @@ public class AVMServicePermissionsTest extends TestCase
avmService.purgeStore(storeName + "-layer-d");
avmService.purgeStore(storeName + "-layer-layer-base");
avmService.purgeStore(storeName + "-layer-layer-layer-base");
+
+ System.out.println(avmService.getStores());
}
}
- public void testSimpleUpdate() throws Exception
+ public void testSimpleUpdate() throws Throwable
{
runAs("admin");
String storeName = "PermissionsTest-" + getName() + "-" + (new Date().getTime());
@@ -556,6 +557,11 @@ public class AVMServicePermissionsTest extends TestCase
fileAcl = node.getAcl();
assertNull(fileAcl);
}
+ catch (Throwable t)
+ {
+ t.printStackTrace();
+ throw t;
+ }
finally
{
avmService.purgeStore(storeName);
diff --git a/source/java/org/alfresco/repo/domain/hibernate/AVMAccessControlListDAO.java b/source/java/org/alfresco/repo/domain/hibernate/AVMAccessControlListDAO.java
index d89dad4d1f..b3cf84fc35 100644
--- a/source/java/org/alfresco/repo/domain/hibernate/AVMAccessControlListDAO.java
+++ b/source/java/org/alfresco/repo/domain/hibernate/AVMAccessControlListDAO.java
@@ -34,6 +34,8 @@ import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.avm.AVMRepository;
import org.alfresco.repo.domain.AccessControlListDAO;
import org.alfresco.repo.domain.DbAccessControlList;
+import org.alfresco.repo.domain.hibernate.AclDaoComponentImpl.Indirection;
+import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.security.permissions.ACLType;
@@ -69,6 +71,10 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
private AclDaoComponent aclDaoComponent;
+ private AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor;
+
+ private HibernateSessionHelper hibernateSessionHelper;
+
/**
* Default constructory.
*/
@@ -91,6 +97,16 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
this.aclDaoComponent = aclDaoComponent;
}
+ public void setAvmSnapShotTriggeredIndexingMethodInterceptor(AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor)
+ {
+ this.avmSnapShotTriggeredIndexingMethodInterceptor = avmSnapShotTriggeredIndexingMethodInterceptor;
+ }
+
+ public void setHibernateSessionHelper(HibernateSessionHelper hibernateSessionHelper)
+ {
+ this.hibernateSessionHelper = hibernateSessionHelper;
+ }
+
public Long getIndirectAcl(NodeRef nodeRef)
{
Pair avmVersionPath = AVMNodeConverter.ToAVMVersionPath(nodeRef);
@@ -233,37 +249,46 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
{
inherited = aclDaoComponent.getInheritedAccessControlList(after);
}
- updateChangedAclsImpl(startingPoint, changes, SetMode.ALL, inherited, after);
+ Map> indirections = buildIndirections();
+ updateChangedAclsImpl(startingPoint, changes, SetMode.ALL, inherited, after, indirections);
}
- private void updateChangedAclsImpl(NodeRef startingPoint, List changes, SetMode mode, Long inherited, Long setAcl)
+ private void updateChangedAclsImpl(NodeRef startingPoint, List changes, SetMode mode, Long inherited, Long setAcl, Map> indirections)
{
- HashMap changeMap = new HashMap();
- HashSet unchangedSet = new HashSet();
- for (AclChange change : changes)
+ hibernateSessionHelper.mark();
+ try
{
- if (change.getBefore() == null)
+ HashMap changeMap = new HashMap();
+ HashSet unchangedSet = new HashSet();
+ for (AclChange change : changes)
{
- // null is treated using the inherited acl
+ if (change.getBefore() == null)
+ {
+ // null is treated using the inherited acl
+ }
+ else if (!change.getBefore().equals(change.getAfter()))
+ {
+ changeMap.put(change.getBefore(), change.getAfter());
+ }
+ else
+ {
+ unchangedSet.add(change.getBefore());
+ }
}
- else if (!change.getBefore().equals(change.getAfter()))
- {
- changeMap.put(change.getBefore(), change.getAfter());
- }
- else
- {
- unchangedSet.add(change.getBefore());
- }
- }
- unchangedSet.add(inherited);
- unchangedSet.add(setAcl);
+ unchangedSet.add(inherited);
+ unchangedSet.add(setAcl);
- if (inherited != null)
- {
- updateReferencingLayeredAcls(startingPoint, inherited);
+ if (inherited != null)
+ {
+ updateReferencingLayeredAcls(startingPoint, inherited, indirections);
+ }
+ updateInheritedChangedAcls(startingPoint, changeMap, unchangedSet, inherited, mode, indirections);
+ updateLayeredAclsChangedByInheritance(changes, changeMap, unchangedSet, indirections);
+ }
+ finally
+ {
+ hibernateSessionHelper.resetAndRemoveMark();
}
- updateInheritedChangedAcls(startingPoint, changeMap, unchangedSet, inherited, mode);
- updateLayeredAclsChangedByInheritance(changes, changeMap, unchangedSet);
}
public void forceCopy(NodeRef nodeRef)
@@ -283,10 +308,33 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
{
throw new InvalidNodeRefException(nodeRef);
}
-
}
- private void updateReferencingLayeredAcls(NodeRef node, Long inherited)
+ private Map> buildIndirections()
+ {
+ Map> answer = new HashMap>();
+
+ List indirections = aclDaoComponent.getAvmIndirections();
+ for (Indirection indirection : indirections)
+ {
+ AVMNodeDescriptor toDesc = fAVMService.lookup(indirection.getToVersion(), indirection.getTo(), true);
+ if (toDesc != null)
+ {
+ Long toId = Long.valueOf(toDesc.getId());
+ Set referees = answer.get(toId);
+ if (referees == null)
+ {
+ referees = new HashSet();
+ answer.put(toId, referees);
+ }
+ referees.add(indirection.getFrom());
+ }
+ }
+
+ return answer;
+ }
+
+ private void updateReferencingLayeredAcls(NodeRef node, Long inherited, Map> indirections)
{
Pair avmVersionPath = AVMNodeConverter.ToAVMVersionPath(node);
int version = avmVersionPath.getFirst();
@@ -304,42 +352,39 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
}
else
{
- List> paths = fAVMService.getHeadPaths(descriptor);
- for (Pair current : paths)
+ Set avmNodeIds = indirections.get(Long.valueOf(descriptor.getId()));
+ if (avmNodeIds != null)
{
- List avmNodeIds = aclDaoComponent.getAvmNodesByIndirection(current.getSecond());
for (Long id : avmNodeIds)
{
// need to fix up inheritance as is has changed
AVMNodeDescriptor layerDesc = new AVMNodeDescriptor(null, null, 0, null, null, null, 0, 0, 0, id, null, 0, null, 0, false, 0, false, 0, 0);
+
List> layerPaths = fAVMRepository.getHeadPaths(layerDesc);
// Update all locations with the updated ACL
+
for (Pair layerPath : layerPaths)
{
- AVMNodeDescriptor test = fAVMService.lookup(-1, layerPath.getSecond());
- if (test.isPrimary())
+ DbAccessControlList target = getAclAsSystem(-1, layerPath.getSecond());
+ if (target != null)
{
- DbAccessControlList target = getAclAsSystem(-1, layerPath.getSecond());
- if (target != null)
+ if (target.getAclType() == ACLType.LAYERED)
{
- if (target.getAclType() == ACLType.LAYERED)
- {
- fAVMService.forceCopy(layerPath.getSecond());
+ fAVMService.forceCopy(layerPath.getSecond());
- List layeredChanges = aclDaoComponent.mergeInheritedAccessControlList(inherited, target.getId());
- NodeRef layeredNode = AVMNodeConverter.ToNodeRef(-1, layerPath.getSecond());
- for (AclChange change : layeredChanges)
+ List layeredChanges = aclDaoComponent.mergeInheritedAccessControlList(inherited, target.getId());
+ NodeRef layeredNode = AVMNodeConverter.ToNodeRef(-1, layerPath.getSecond());
+ for (AclChange change : layeredChanges)
+ {
+ if (change.getBefore().equals(target.getId()))
{
- if (change.getBefore().equals(target.getId()))
+ Long newInherited = null;
+ if (change.getAfter() != null)
{
- Long newInherited = null;
- if (change.getAfter() != null)
- {
- newInherited = aclDaoComponent.getInheritedAccessControlList(change.getAfter());
- }
- updateChangedAclsImpl(layeredNode, layeredChanges, SetMode.DIRECT_ONLY, newInherited, change.getAfter());
- break;
+ newInherited = aclDaoComponent.getInheritedAccessControlList(change.getAfter());
}
+ updateChangedAclsImpl(layeredNode, layeredChanges, SetMode.DIRECT_ONLY, newInherited, change.getAfter(), indirections);
+ break;
}
}
}
@@ -355,7 +400,7 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
}
}
- private void updateLayeredAclsChangedByInheritance(List changes, HashMap changeMap, Set unchanged)
+ private void updateLayeredAclsChangedByInheritance(List changes, HashMap changeMap, Set unchanged, Map> indirections)
{
for (AclChange change : changes)
{
@@ -375,14 +420,16 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
// No need to force COW - any inherited ACL will have COWED if the top ACL required it
setAclAsSystem(path.getSecond(), aclDaoComponent.getDbAccessControlList(change.getAfter()));
NodeRef layeredNode = AVMNodeConverter.ToNodeRef(-1, path.getSecond());
- updateInheritedChangedAcls(layeredNode, changeMap, unchanged, aclDaoComponent.getInheritedAccessControlList(change.getAfter()), SetMode.DIRECT_ONLY);
+ updateInheritedChangedAcls(layeredNode, changeMap, unchanged, aclDaoComponent.getInheritedAccessControlList(change.getAfter()), SetMode.DIRECT_ONLY,
+ indirections);
}
}
}
}
}
- private void updateInheritedChangedAcls(NodeRef startingPoint, HashMap changeMap, Set unchanged, Long unsetAcl, SetMode mode)
+ private void updateInheritedChangedAcls(NodeRef startingPoint, HashMap changeMap, Set unchanged, Long unsetAcl, SetMode mode,
+ Map> indirections)
{
// Walk children and fix up any that reference the given list ..
Pair avmVersionPath = AVMNodeConverter.ToAVMVersionPath(startingPoint);
@@ -404,9 +451,10 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
if (descriptor.isLayeredDirectory())
{
- setInheritanceForDirectChildren(descriptor, changeMap, aclDaoComponent.getInheritedAccessControlList(getAclAsSystem(-1, descriptor.getPath()).getId()));
+ setInheritanceForDirectChildren(descriptor, changeMap, aclDaoComponent.getInheritedAccessControlList(getAclAsSystem(-1, descriptor.getPath()).getId()),
+ indirections);
}
- fixUpAcls(descriptor, changeMap, unchanged, unsetAcl, mode);
+ fixUpAcls(descriptor, changeMap, unchanged, unsetAcl, mode, indirections);
}
}
catch (AVMException e)
@@ -415,9 +463,9 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
}
}
- private void fixUpAcls(AVMNodeDescriptor descriptor, Map changes, Set unchanged, Long unsetAcl, SetMode mode)
+ private void fixUpAcls(AVMNodeDescriptor descriptor, Map changes, Set unchanged, Long unsetAcl, SetMode mode, Map> indirections)
{
- DbAccessControlList acl = getAclAsSystem(-1, descriptor.getPath());
+ DbAccessControlList acl = getAclAsSystem(-1, descriptor.getPath());
Long id = null;
if (acl != null)
{
@@ -429,7 +477,7 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
// No need to force COW - ACL should have COWed if required
setAclAsSystem(descriptor.getPath(), aclDaoComponent.getDbAccessControlList(unsetAcl));
NodeRef nodeRef = AVMNodeConverter.ToNodeRef(-1, descriptor.getPath());
- updateReferencingLayeredAcls(nodeRef, unsetAcl);
+ updateReferencingLayeredAcls(nodeRef, unsetAcl, indirections);
}
else if (changes.containsKey(id))
{
@@ -466,16 +514,24 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
}
for (AVMNodeDescriptor child : children.values())
{
- fixUpAcls(child, changes, unchanged, unsetAcl, mode);
+ hibernateSessionHelper.mark();
+ try
+ {
+ fixUpAcls(child, changes, unchanged, unsetAcl, mode, indirections);
+ }
+ finally
+ {
+ hibernateSessionHelper.resetAndRemoveMark();
+ }
}
}
}
- private void setInheritanceForDirectChildren(AVMNodeDescriptor descriptor, Map changeMap, Long mergeFrom)
+ private void setInheritanceForDirectChildren(AVMNodeDescriptor descriptor, Map changeMap, Long mergeFrom, Map> indirections)
{
List changes = new ArrayList();
- setFixedAcls(descriptor, mergeFrom, changes, SetMode.DIRECT_ONLY, false);
+ setFixedAcls(descriptor, mergeFrom, changes, SetMode.DIRECT_ONLY, false, indirections);
for (AclChange change : changes)
{
if (!change.getBefore().equals(change.getAfter()))
@@ -498,9 +554,10 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
String path = avmVersionPath.getSecond();
try
{
+ Map> indirections = buildIndirections();
List changes = new ArrayList();
AVMNodeDescriptor descriptor = fAVMService.lookup(version, path);
- setFixedAcls(descriptor, mergeFrom, changes, SetMode.ALL, false);
+ setFixedAcls(descriptor, mergeFrom, changes, SetMode.ALL, false, indirections);
return changes;
}
@@ -510,7 +567,7 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
}
}
- public void setFixedAcls(AVMNodeDescriptor descriptor, Long mergeFrom, List changes, SetMode mode, boolean set)
+ public void setFixedAcls(AVMNodeDescriptor descriptor, Long mergeFrom, List changes, SetMode mode, boolean set, Map> indirections)
{
if (descriptor == null)
{
@@ -527,7 +584,7 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
if (previous == null)
{
NodeRef nodeRef = AVMNodeConverter.ToNodeRef(-1, descriptor.getPath());
- updateReferencingLayeredAcls(nodeRef, mergeFrom);
+ updateReferencingLayeredAcls(nodeRef, mergeFrom, indirections);
}
}
@@ -554,8 +611,15 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
if (acl == null)
{
- setFixedAcls(child, mergeFrom, changes, mode, true);
-
+ hibernateSessionHelper.mark();
+ try
+ {
+ setFixedAcls(child, mergeFrom, changes, mode, true, indirections);
+ }
+ finally
+ {
+ hibernateSessionHelper.resetAndRemoveMark();
+ }
}
else if (acl.getAclType() == ACLType.LAYERED)
{
@@ -573,16 +637,32 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
{
if (change.getBefore().equals(acl.getId()))
{
- setAclAsSystem(child.getPath(), aclDaoComponent.getDbAccessControlList(change.getAfter()));
- setFixedAcls(child, aclDaoComponent.getInheritedAccessControlList(change.getAfter()), newChanges, SetMode.DIRECT_ONLY, false);
- changes.addAll(newChanges);
- break;
+ hibernateSessionHelper.mark();
+ try
+ {
+ setAclAsSystem(child.getPath(), aclDaoComponent.getDbAccessControlList(change.getAfter()));
+ setFixedAcls(child, aclDaoComponent.getInheritedAccessControlList(change.getAfter()), newChanges, SetMode.DIRECT_ONLY, false, indirections);
+ changes.addAll(newChanges);
+ break;
+ }
+ finally
+ {
+ hibernateSessionHelper.resetAndRemoveMark();
+ }
}
}
}
else
{
- setFixedAcls(child, mergeFrom, changes, mode, true);
+ hibernateSessionHelper.mark();
+ try
+ {
+ setFixedAcls(child, mergeFrom, changes, mode, true, indirections);
+ }
+ finally
+ {
+ hibernateSessionHelper.resetAndRemoveMark();
+ }
}
}
@@ -599,11 +679,31 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
{
CounterSet result = new CounterSet();
List stores = fAVMService.getStores();
+ Map> indirections = buildIndirections();
for (AVMStoreDescriptor store : stores)
{
AVMNodeDescriptor root = fAVMService.getStoreRoot(-1, store.getName());
- CounterSet update = fixOldAvmAcls(root);
- result.add(update);
+ CounterSet update;
+ switch (avmSnapShotTriggeredIndexingMethodInterceptor.getStoreType(store.getName()))
+ {
+ case AUTHOR:
+ case AUTHOR_PREVIEW:
+ case AUTHOR_WORKFLOW:
+ case AUTHOR_WORKFLOW_PREVIEW:
+ case STAGING:
+ case STAGING_PREVIEW:
+ case WORKFLOW:
+ case WORKFLOW_PREVIEW:
+ AVMNodeDescriptor www = fAVMService.lookup(-1, store.getName() + ":/www");
+ update = fixOldAvmAcls(www, false, indirections);
+ result.add(update);
+ break;
+ case UNKNOWN:
+ default:
+ update = fixOldAvmAcls(root, true, indirections);
+ result.add(update);
+ }
+
}
HashMap toReturn = new HashMap();
@@ -614,20 +714,32 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
toReturn.put(ACLType.OLD, Integer.valueOf(result.get(ACLType.OLD).getCounter()));
toReturn.put(ACLType.SHARED, Integer.valueOf(result.get(ACLType.SHARED).getCounter()));
return toReturn;
-
}
- private CounterSet fixOldAvmAcls(AVMNodeDescriptor node)
+ private CounterSet fixOldAvmAcls(AVMNodeDescriptor node, boolean searchDirectories, Map> indirections)
+ {
+ hibernateSessionHelper.mark();
+ try
+ {
+ return fixOldAvmAclsImpl(node, searchDirectories, indirections);
+ }
+ finally
+ {
+ hibernateSessionHelper.resetAndRemoveMark();
+ }
+ }
+
+ private CounterSet fixOldAvmAclsImpl(AVMNodeDescriptor node, boolean searchDirectories, Map> indirections)
{
CounterSet result = new CounterSet();
// Do the children first
- if (node.isDirectory())
+ if (searchDirectories && node.isDirectory())
{
Map children = fAVMRepository.getListingDirect(node, true);
for (AVMNodeDescriptor child : children.values())
{
- CounterSet update = fixOldAvmAcls(child);
+ CounterSet update = fixOldAvmAcls(child, searchDirectories, indirections);
result.add(update);
}
}
@@ -660,7 +772,7 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
List changes = new ArrayList();
- setFixedAcls(node, aclDaoComponent.getInheritedAccessControlList(id), changes, SetMode.DIRECT_ONLY, false);
+ setFixedAcls(node, aclDaoComponent.getInheritedAccessControlList(id), changes, SetMode.DIRECT_ONLY, false, indirections);
for (AclChange change : changes)
{
@@ -706,7 +818,7 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
}
List changes = new ArrayList();
- setFixedAcls(node, aclDaoComponent.getInheritedAccessControlList(getAclAsSystem(-1, node.getPath()).getId()), changes, SetMode.DIRECT_ONLY, false);
+ setFixedAcls(node, aclDaoComponent.getInheritedAccessControlList(getAclAsSystem(-1, node.getPath()).getId()), changes, SetMode.DIRECT_ONLY, false, indirections);
for (AclChange change : changes)
{
@@ -746,7 +858,7 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
}
List changes = new ArrayList();
- setFixedAcls(node, aclDaoComponent.getInheritedAccessControlList(getAclAsSystem(-1, node.getPath()).getId()), changes, SetMode.DIRECT_ONLY, false);
+ setFixedAcls(node, aclDaoComponent.getInheritedAccessControlList(getAclAsSystem(-1, node.getPath()).getId()), changes, SetMode.DIRECT_ONLY, false, indirections);
for (AclChange change : changes)
{
@@ -815,47 +927,55 @@ public class AVMAccessControlListDAO implements AccessControlListDAO
counter += i;
}
}
-
+
private DbAccessControlList getStoreAclAsSystem(final String storeName)
{
- return AuthenticationUtil.runAs(new RunAsWork(){
+ return AuthenticationUtil.runAs(new RunAsWork()
+ {
public DbAccessControlList doWork() throws Exception
{
return fAVMRepository.getStoreAcl(storeName);
- }}, AuthenticationUtil.getSystemUserName());
+ }
+ }, AuthenticationUtil.getSystemUserName());
}
-
+
private void setStoreAclAsSystem(final String storeName, final DbAccessControlList acl)
{
- AuthenticationUtil.runAs(new RunAsWork