diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index 92636e5163..9fa1c90dfd 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -252,7 +252,10 @@ db.pool.abandoned.time=300 audit.enabled=false audit.repository.enabled=true audit.cmischangelog.enabled=true -audit.useNewConfig=true +# Setting this flag to true will cause alfresco/auditConfig.xml to be ignored +# when audit is enabled. When false both alfresco/auditConfig.xml and +# alfresco/audit/*.xml will be used. +audit.useNewConfig=false # Email configuration mail.host= diff --git a/source/java/org/alfresco/repo/audit/AuditComponent.java b/source/java/org/alfresco/repo/audit/AuditComponent.java index 15c0768e16..8731431445 100644 --- a/source/java/org/alfresco/repo/audit/AuditComponent.java +++ b/source/java/org/alfresco/repo/audit/AuditComponent.java @@ -94,6 +94,13 @@ public interface AuditComponent * V3.2 from here on. Put all fixes to the older audit code before this point, please. */ + /** + * Determines whether audit is globally enabled or disabled. + * + * @return true, if audit is enabled + */ + public boolean isAuditEnabled(); + /** * Determines whether the given source path is mapped to any audit applications. Allows optimizations to be made in * calling components. diff --git a/source/java/org/alfresco/repo/audit/AuditComponentImpl.java b/source/java/org/alfresco/repo/audit/AuditComponentImpl.java index 66948b77e4..98dccd8405 100644 --- a/source/java/org/alfresco/repo/audit/AuditComponentImpl.java +++ b/source/java/org/alfresco/repo/audit/AuditComponentImpl.java @@ -955,13 +955,22 @@ public class AuditComponentImpl implements AuditComponent } } + /** + * {@inheritDoc} + * @since 3.2 + */ + public boolean isAuditEnabled() + { + return auditModelRegistry.isAuditEnabled(); + } + /** * {@inheritDoc} * @since 3.2 */ public boolean isSourcePathMapped(String sourcePath) { - return !auditModelRegistry.getAuditPathMapper().isEmpty(); + return isAuditEnabled() && !auditModelRegistry.getAuditPathMapper().isEmpty(); } /** diff --git a/source/java/org/alfresco/repo/audit/AuditMethodInterceptor.java b/source/java/org/alfresco/repo/audit/AuditMethodInterceptor.java index 91213b90cf..03446addf5 100644 --- a/source/java/org/alfresco/repo/audit/AuditMethodInterceptor.java +++ b/source/java/org/alfresco/repo/audit/AuditMethodInterceptor.java @@ -102,7 +102,6 @@ public class AuditMethodInterceptor implements MethodInterceptor private boolean useNewConfig = false; private final ThreadLocal inAudit = new ThreadLocal(); - private final ThreadLocal auditEnabled = new ThreadLocal(); public AuditMethodInterceptor() { @@ -136,44 +135,16 @@ public class AuditMethodInterceptor implements MethodInterceptor public Object invoke(MethodInvocation mi) throws Throwable { - // Cache the enabled flag at the top of the stack - Boolean wasEnabled = auditEnabled.get(); - try + if(!auditComponent.isAuditEnabled()) { - boolean enabled; - if (wasEnabled == null) - { - // There hasn't been an invocation in this thread yet, so check whether we are currently enabled in the - // audit subsystem - enabled = this.auditComponent.isSourcePathMapped(AUDIT_PATH_API_ROOT); - auditEnabled.set(enabled); - } - else - { - enabled = wasEnabled; - } - - if(!enabled) - { - // No auditing - return mi.proceed(); - } - else if (useNewConfig) - { - // New configuration to be used - return proceed(mi); - } - else - { - // Use previous configuration - return auditComponent.audit(mi); - } + // No auditing + return mi.proceed(); } - finally + else { - auditEnabled.set(wasEnabled); + // New configuration will be used and optionally old configuration if useNewConfig=false + return proceed(mi); } - } /** @@ -188,41 +159,50 @@ public class AuditMethodInterceptor implements MethodInterceptor */ private Object proceed(MethodInvocation mi) throws Throwable { - Auditable auditableDef = mi.getMethod().getAnnotation(Auditable.class); - if (auditableDef == null) - { - // No annotation, so just continue as normal - return mi.proceed(); - } - - // First get the argument map, if present - Object[] args = mi.getArguments(); - Map namedArguments = getInvocationArguments(auditableDef, args); - // Get the service name - String serviceName = publicServiceIdentifier.getPublicServiceName(mi); - if (serviceName == null) - { - // Not a public service - return mi.proceed(); - } - String methodName = mi.getMethod().getName(); - - // Are we in a nested audit + // Are we in a nested audit? Boolean wasInAudit = inAudit.get(); - // TODO: Need to make this configurable for the interceptor or a conditional mapping for audit - if (wasInAudit != null) - { - return mi.proceed(); - } - // Record that we have entered an audit method - inAudit.set(Boolean.TRUE); try { + // If we are already in a nested audit call, there is nothing to do + if (wasInAudit != null) + { + return useNewConfig ? mi.proceed() : auditComponent.audit(mi); + } + + // If there are no mapped paths, there is nothing to do + if (!this.auditComponent.isSourcePathMapped(AUDIT_PATH_API_ROOT)) + { + // We can ignore the rest of the stack too + inAudit.set(Boolean.TRUE); + return useNewConfig ? mi.proceed() : auditComponent.audit(mi); + } + + Auditable auditableDef = mi.getMethod().getAnnotation(Auditable.class); + if (auditableDef == null) + { + // No annotation, so just continue as normal + return useNewConfig ? mi.proceed() : auditComponent.audit(mi); + } + + // First get the argument map, if present + Object[] args = mi.getArguments(); + Map namedArguments = getInvocationArguments(auditableDef, args); + // Get the service name + String serviceName = publicServiceIdentifier.getPublicServiceName(mi); + if (serviceName == null) + { + // Not a public service + return useNewConfig ? mi.proceed() : auditComponent.audit(mi); + } + String methodName = mi.getMethod().getName(); + + // Record that we have entered an audit method + inAudit.set(Boolean.TRUE); return proceedWithAudit(mi, auditableDef, serviceName, methodName, namedArguments); } finally { - inAudit.set(wasInAudit); + inAudit.set(wasInAudit); } } @@ -251,7 +231,7 @@ public class AuditMethodInterceptor implements MethodInterceptor Throwable thrown = null; try { - ret = mi.proceed(); + ret = useNewConfig ? mi.proceed() : auditComponent.audit(mi); } catch (Throwable e) { diff --git a/source/java/org/alfresco/repo/audit/model/AuditModelRegistry.java b/source/java/org/alfresco/repo/audit/model/AuditModelRegistry.java index 9c8d097605..f106ab9246 100644 --- a/source/java/org/alfresco/repo/audit/model/AuditModelRegistry.java +++ b/source/java/org/alfresco/repo/audit/model/AuditModelRegistry.java @@ -24,8 +24,6 @@ */ package org.alfresco.repo.audit.model; -import java.net.URL; - import org.alfresco.util.PathMapper; /** @@ -41,14 +39,20 @@ public interface AuditModelRegistry /** * Method to load audit models into memory. This method is also responsible for persisting - * the audit models for later retrieval. Models are loaded from the locations given by the - * {@link #registerModel(URL) register} methods. + * the audit models for later retrieval. *

* Note, the models are loaded in a new transaction, so this method can be called by any code * at any time. */ public void loadAuditModels(); + /** + * Determines whether audit is globally enabled or disabled. + * + * @return true, if audit is enabled + */ + public boolean isAuditEnabled(); + /** * Get the application model for the given root key (as defined on the application) * diff --git a/source/java/org/alfresco/repo/audit/model/AuditModelRegistryImpl.java b/source/java/org/alfresco/repo/audit/model/AuditModelRegistryImpl.java index cb7207aff0..f3c9181d07 100644 --- a/source/java/org/alfresco/repo/audit/model/AuditModelRegistryImpl.java +++ b/source/java/org/alfresco/repo/audit/model/AuditModelRegistryImpl.java @@ -152,6 +152,15 @@ public class AuditModelRegistryImpl extends AbstractPropertyBackedBean implement start(); } + /** + * {@inheritDoc} + */ + public boolean isAuditEnabled() + { + String value = getProperty(PROPERTY_AUDIT_ENABLED); + return value != null && value.equalsIgnoreCase("true"); + } + /** * Enables audit and registers an audit model at a given URL. Does not register across the cluster and should only * be used for unit test purposes.