mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Audit - working without filters
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3646 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
425
source/java/org/alfresco/repo/audit/AuditComponentImpl.java
Normal file
425
source/java/org/alfresco/repo/audit/AuditComponentImpl.java
Normal file
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.repo.audit;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.service.Auditable;
|
||||
import org.alfresco.service.NotAuditable;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* The default audit component implementation. TODO: Implement before, after and exception filtering. At the moment these filters are ignired. TODO: Respect audit internal - at the
|
||||
* moment audit internal is fixed to false.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public class AuditComponentImpl implements AuditComponent
|
||||
{
|
||||
/**
|
||||
* The application name to use for audit entries generated by method interception around public services.
|
||||
*/
|
||||
private static final String SYSTEM_APPLICATION = "SystemMethodInterceptor";
|
||||
|
||||
/**
|
||||
* Logging
|
||||
*/
|
||||
private static Log s_logger = LogFactory.getLog(AuditComponentImpl.class);
|
||||
|
||||
/**
|
||||
* Suspend resume auditing
|
||||
*/
|
||||
private static ThreadLocal<Boolean> auditFlag = new ThreadLocal<Boolean>();
|
||||
|
||||
/**
|
||||
* IOC
|
||||
*/
|
||||
private PublicServiceIdentifier publicServiceIdentifier;
|
||||
|
||||
private AuditConfiguration auditConfiguration;
|
||||
|
||||
private AuditDAO auditDAO;
|
||||
|
||||
private AuditDAO auditFailedDAO;
|
||||
|
||||
private AuditModel auditModel;
|
||||
|
||||
/**
|
||||
* Keep hold of the host where the audit occurs. TODO: Check that we get the correct address ...
|
||||
*/
|
||||
|
||||
private InetAddress auditHost;
|
||||
|
||||
public AuditComponentImpl()
|
||||
{
|
||||
super();
|
||||
// Initialise the host address
|
||||
try
|
||||
{
|
||||
auditHost = InetAddress.getLocalHost();
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
s_logger.error("Failed to get local host address", e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* IOC property setters
|
||||
*/
|
||||
|
||||
public void setAuditDAO(AuditDAO auditDAO)
|
||||
{
|
||||
this.auditDAO = auditDAO;
|
||||
}
|
||||
|
||||
public void setAuditFailedDAO(AuditDAO auditFailedDAO)
|
||||
{
|
||||
this.auditFailedDAO = auditFailedDAO;
|
||||
}
|
||||
|
||||
public void setAuditConfiguration(AuditConfiguration auditConfiguration)
|
||||
{
|
||||
this.auditConfiguration = auditConfiguration;
|
||||
}
|
||||
|
||||
public void setPublicServiceIdentifier(PublicServiceIdentifier publicServiceIdentifier)
|
||||
{
|
||||
this.publicServiceIdentifier = publicServiceIdentifier;
|
||||
}
|
||||
|
||||
public void setAuditModel(AuditModel auditModel)
|
||||
{
|
||||
this.auditModel = auditModel;
|
||||
}
|
||||
|
||||
public Object audit(MethodInvocation mi) throws Throwable
|
||||
{
|
||||
if ((auditFlag.get() == null) || (!auditFlag.get().booleanValue()))
|
||||
{
|
||||
try
|
||||
{
|
||||
auditFlag.set(Boolean.TRUE);
|
||||
|
||||
Method method = mi.getMethod();
|
||||
String methodName = method.getName();
|
||||
String serviceName = publicServiceIdentifier.getPublicServiceName(mi);
|
||||
if (method.isAnnotationPresent(Auditable.class))
|
||||
{
|
||||
|
||||
if (serviceName != null)
|
||||
{
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("Auditing - " + serviceName + "." + methodName);
|
||||
}
|
||||
return auditImpl(mi);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("UnknownService." + methodName);
|
||||
}
|
||||
return auditImpl(mi);
|
||||
}
|
||||
|
||||
}
|
||||
else if (method.isAnnotationPresent(NotAuditable.class))
|
||||
{
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("Not Audited. " + serviceName + "." + methodName);
|
||||
}
|
||||
return mi.proceed();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("Unannotated service method " + serviceName + "." + methodName);
|
||||
}
|
||||
throw new RuntimeException("Unannotated service method " + serviceName + "." + methodName);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
auditFlag.set(Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return mi.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Audit a method invocation
|
||||
*/
|
||||
public Object auditImpl(MethodInvocation mi) throws Throwable
|
||||
{
|
||||
AuditInfo auditInfo = new AuditInfo(auditConfiguration);
|
||||
// RecordOptions recordOptions = auditModel.getAuditRecordOptions(mi);
|
||||
AuditMode auditMode = AuditMode.UNSET;
|
||||
try
|
||||
{
|
||||
auditMode = beforeInvocation(auditMode, auditInfo, mi);
|
||||
Object o = mi.proceed();
|
||||
auditMode = postInvocation(auditMode, auditInfo, mi, o);
|
||||
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.SUCCESS))
|
||||
{
|
||||
auditDAO.audit(auditInfo);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
auditMode = onError(auditMode, auditInfo, mi, t);
|
||||
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.FAIL))
|
||||
{
|
||||
try
|
||||
{
|
||||
auditFailedDAO.audit(auditInfo);
|
||||
}
|
||||
catch (Throwable tt)
|
||||
{
|
||||
throw new AuditException("Failed to audit exception", new Object[] { tt }, t);
|
||||
}
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to set auditable properties and to determine if auditing is required when an exception is caught in the audited method.
|
||||
*
|
||||
* @param auditMode
|
||||
* @param auditInfo
|
||||
* @param t
|
||||
* @return
|
||||
*/
|
||||
private AuditMode onError(AuditMode auditMode, AuditInfo auditInfo, MethodInvocation mi, Throwable t)
|
||||
{
|
||||
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.FAIL))
|
||||
{
|
||||
auditInfo.setFail(true);
|
||||
auditInfo.setThrowable(t);
|
||||
}
|
||||
|
||||
return auditMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to set audited information after method invocation and to determine if auditing should take place based on the method return value.
|
||||
*
|
||||
* @param auditMode
|
||||
* @param auditInfo
|
||||
* @param mi
|
||||
* @param returnObject
|
||||
* @return
|
||||
*/
|
||||
private AuditMode postInvocation(AuditMode auditMode, AuditInfo auditInfo, MethodInvocation mi, Object returnObject)
|
||||
{
|
||||
if (returnObject == null)
|
||||
{
|
||||
auditInfo.setReturnObject(null);
|
||||
}
|
||||
else if (returnObject instanceof Serializable)
|
||||
{
|
||||
auditInfo.setReturnObject((Serializable) returnObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
auditInfo.setReturnObject(returnObject.toString());
|
||||
}
|
||||
return auditMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set auditable information and determine if auditing is required before method invocation. This would normally be based on the method arguments.
|
||||
*
|
||||
* @param auditMode
|
||||
* @param auditInfo
|
||||
* @param mi
|
||||
* @return
|
||||
*/
|
||||
private AuditMode beforeInvocation(AuditMode auditMode, AuditInfo auditInfo, MethodInvocation mi)
|
||||
{
|
||||
AuditMode effectiveAuditMode = auditModel.beforeExecution(auditMode, mi);
|
||||
|
||||
if (auditMode != AuditMode.NONE)
|
||||
{
|
||||
String methodName = mi.getMethod().getName();
|
||||
String serviceName = publicServiceIdentifier.getPublicServiceName(mi);
|
||||
auditInfo.setAuditApplication(SYSTEM_APPLICATION);
|
||||
auditInfo.setAuditConfiguration(auditConfiguration);
|
||||
auditInfo.setAuditMethod(methodName);
|
||||
auditInfo.setAuditService(serviceName);
|
||||
auditInfo.setClientAddress(null);
|
||||
auditInfo.setDate(new Date());
|
||||
auditInfo.setFail(false);
|
||||
auditInfo.setFiltered(false);
|
||||
auditInfo.setHostAddress(auditHost);
|
||||
auditInfo.setKeyGUID(null);
|
||||
auditInfo.setKeyPropertiesAfter(null);
|
||||
auditInfo.setKeyPropertiesBefore(null);
|
||||
auditInfo.setKeyStore(null);
|
||||
auditInfo.setMessage(null);
|
||||
if (mi.getArguments() != null)
|
||||
{
|
||||
Serializable[] serArgs = new Serializable[mi.getArguments().length];
|
||||
for (int i = 0; i < mi.getArguments().length; i++)
|
||||
{
|
||||
if (mi.getArguments()[i] == null)
|
||||
{
|
||||
serArgs[i] = null;
|
||||
}
|
||||
else if (mi.getArguments()[i] instanceof Serializable)
|
||||
{
|
||||
serArgs[i] = (Serializable) mi.getArguments()[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
serArgs[i] = mi.getArguments()[i].toString();
|
||||
}
|
||||
}
|
||||
auditInfo.setMethodArguments(serArgs);
|
||||
}
|
||||
auditInfo.setPath(null);
|
||||
auditInfo.setReturnObject(null);
|
||||
auditInfo.setSessionId(null);
|
||||
auditInfo.setThrowable(null);
|
||||
auditInfo.setTxId(AlfrescoTransactionSupport.getTransactionId());
|
||||
auditInfo.setUserIdentifier(AuthenticationUtil.getCurrentUserName());
|
||||
}
|
||||
|
||||
return effectiveAuditMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple audit entry Currently we ignore filtering here.
|
||||
*/
|
||||
public void audit(String source, String description, NodeRef key, Object... args)
|
||||
{
|
||||
AuditInfo auditInfo = new AuditInfo(auditConfiguration);
|
||||
// RecordOptions recordOptions = auditModel.getAuditRecordOptions(mi);
|
||||
AuditMode auditMode = AuditMode.UNSET;
|
||||
try
|
||||
{
|
||||
auditMode = onApplicationAudit(auditMode, auditInfo, source, description, key, args);
|
||||
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.SUCCESS))
|
||||
{
|
||||
auditDAO.audit(auditInfo);
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
auditMode = onError(auditMode, auditInfo, t, source, description, key, args);
|
||||
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.FAIL))
|
||||
{
|
||||
try
|
||||
{
|
||||
auditFailedDAO.audit(auditInfo);
|
||||
}
|
||||
catch (Throwable tt)
|
||||
{
|
||||
throw new AuditException("Failed to audit exception", new Object[] { tt }, t);
|
||||
}
|
||||
}
|
||||
throw new AuditException("Application audit failed", t);
|
||||
}
|
||||
}
|
||||
|
||||
private AuditMode onApplicationAudit(AuditMode auditMode, AuditInfo auditInfo, String source, String description,
|
||||
NodeRef key, Object... args)
|
||||
{
|
||||
AuditMode effectiveAuditMode = auditModel.beforeExecution(auditMode, source, description, key, args);
|
||||
|
||||
if (auditMode != AuditMode.NONE)
|
||||
{
|
||||
if(source.equals(SYSTEM_APPLICATION))
|
||||
{
|
||||
throw new AuditException("Application audit can not use the reserved identifier "+SYSTEM_APPLICATION);
|
||||
}
|
||||
|
||||
auditInfo.setAuditApplication(source);
|
||||
auditInfo.setAuditConfiguration(auditConfiguration);
|
||||
auditInfo.setAuditMethod(null);
|
||||
auditInfo.setAuditService(null);
|
||||
auditInfo.setClientAddress(null);
|
||||
auditInfo.setDate(new Date());
|
||||
auditInfo.setFail(false);
|
||||
auditInfo.setFiltered(false);
|
||||
auditInfo.setHostAddress(auditHost);
|
||||
auditInfo.setKeyGUID(null);
|
||||
auditInfo.setKeyPropertiesAfter(null);
|
||||
auditInfo.setKeyPropertiesBefore(null);
|
||||
auditInfo.setKeyStore(null);
|
||||
auditInfo.setMessage(description);
|
||||
if (args != null)
|
||||
{
|
||||
Serializable[] serArgs = new Serializable[args.length];
|
||||
for (int i = 0; i < args.length; i++)
|
||||
{
|
||||
if (args[i] == null)
|
||||
{
|
||||
serArgs[i] = null;
|
||||
}
|
||||
else if (args[i] instanceof Serializable)
|
||||
{
|
||||
serArgs[i] = (Serializable) args[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
serArgs[i] = args[i].toString();
|
||||
}
|
||||
}
|
||||
auditInfo.setMethodArguments(serArgs);
|
||||
}
|
||||
auditInfo.setPath(null);
|
||||
auditInfo.setReturnObject(null);
|
||||
auditInfo.setSessionId(null);
|
||||
auditInfo.setThrowable(null);
|
||||
auditInfo.setTxId(AlfrescoTransactionSupport.getTransactionId());
|
||||
auditInfo.setUserIdentifier(AuthenticationUtil.getCurrentUserName());
|
||||
}
|
||||
|
||||
return effectiveAuditMode;
|
||||
}
|
||||
|
||||
private AuditMode onError(AuditMode auditMode, AuditInfo auditInfo, Throwable t, String source, String description,
|
||||
NodeRef key, Object... args)
|
||||
{
|
||||
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.FAIL))
|
||||
{
|
||||
auditInfo.setFail(true);
|
||||
auditInfo.setThrowable(t);
|
||||
}
|
||||
|
||||
return auditMode;
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user