From eaa39abc27f9132f4eb661ffbf997fad1c664703 Mon Sep 17 00:00:00 2001 From: Dave Ward Date: Fri, 26 Feb 2010 13:54:46 +0000 Subject: [PATCH] Improved backward compatibility with default audit settings - audit.useNewConfig=false is now the default setting and has a new meaning - In this mode, audit information is broadcast to BOTH the old and new audit configuration, meaning that e.g. you can enjoy new RM and CMIS auditing capabilities whilst still retaining compatibility with your old audit configuration - When audit.useNewConfig=true only the new config/alfresco/audit/*.xml configuration will be used exclusively. NOT config/auditConfig.xml. - Note that auditing is still switched off by default and must be switched on with audit.enabled=true - You can switch on and off individual applications in the new config using - audit.repository.enabled - audit.cmischangelog.enabled - audit.dod5015.enabled - Simple! git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18885 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/repository.properties | 5 +- .../alfresco/repo/audit/AuditComponent.java | 7 ++ .../repo/audit/AuditComponentImpl.java | 11 +- .../repo/audit/AuditMethodInterceptor.java | 108 +++++++----------- .../repo/audit/model/AuditModelRegistry.java | 12 +- .../audit/model/AuditModelRegistryImpl.java | 9 ++ 6 files changed, 82 insertions(+), 70 deletions(-) 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.