mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-11-05 15:32:21 +00:00
.externalToolBuilders
config
source
cpp
java
org
alfresco
filesys
jcr
linkvalidation
model
repo
action
admin
attributes
audit
hibernate
Audit.hbm.xml
AuditConfig.java
AuditConfigImpl.java
AuditDate.java
AuditDateImpl.java
AuditFact.java
AuditFactImpl.java
AuditInfoImpl.java
AuditSource.java
AuditSourceImpl.java
HibernateAuditDAO.java
model
ApplicationAuditModel.java
AuditComponent.java
AuditComponentImpl.java
AuditConfiguration.java
AuditConfigurationImpl.java
AuditDAO.java
AuditException.java
AuditInfo.java
AuditMethodInterceptor.java
AuditMode.java
AuditModel.java
AuditServiceImpl.java
AuditServiceTest.java
AuditState.java
AuditableAspect.java
AuditableAspectTest.java
MethodAuditModel.java
PublicServiceIdentifier.java
PublicServiceIdentifierImpl.java
RecordOptions.java
avm
cache
clt
coci
config
configuration
content
copy
deploy
descriptor
dictionary
domain
exporter
forum
i18n
importer
jscript
lock
model
module
node
ownable
policy
processor
remote
rule
search
security
service
template
tenant
transaction
version
workflow
sandbox
service
tools
util
apache
queryRegister.dtd
meta-inf
test-resources
web
.classpath
.project
build.xml
6349: Build fix after ReadPermissions was added to the permission model
6350: CIFS file rename fixes
6352: Management of avmsubmittedaspect, particularly as applies to newly created directories
6353: Added assemble to ignore property pattern
6354: Deployment project build stuff
6355: Fix for AR-1245 (Do not authenticate in a read only TX as it could create a person object)
6356: Office 2003 Add-Ins - Fixes to installers to support Vista
6357: Office Add-In web scripts - Updated to support the new Office 2007 extensions (.docx, .xlsx, .pptx)
6358: Fix for AR-1392 - Audit string lengths
6359: Remove unwanted rule model from repo
Fix issue with update rules on spaces causing documents to be deleted in CIFS
6360: Office 2003 Add-In Installers, Vista fixes
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6723 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
552 lines
20 KiB
Java
552 lines
20 KiB
Java
/*
|
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
* As a special exception to the terms and conditions of version 2.0 of
|
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
|
* FLOSS exception. You should have recieved a copy of the text describing
|
|
* the FLOSS exception, and it is also available here:
|
|
* http://www.alfresco.com/legal/licensing"
|
|
*/
|
|
package org.alfresco.repo.audit.hibernate;
|
|
|
|
import java.io.BufferedInputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.Serializable;
|
|
import java.util.ArrayList;
|
|
import java.util.Calendar;
|
|
import java.util.Collections;
|
|
import java.util.Date;
|
|
import java.util.GregorianCalendar;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
|
|
import org.alfresco.error.AlfrescoRuntimeException;
|
|
import org.alfresco.repo.audit.AuditComponentImpl;
|
|
import org.alfresco.repo.audit.AuditConfiguration;
|
|
import org.alfresco.repo.audit.AuditDAO;
|
|
import org.alfresco.repo.audit.AuditState;
|
|
import org.alfresco.repo.content.ContentContext;
|
|
import org.alfresco.repo.content.ContentStore;
|
|
import org.alfresco.repo.content.MimetypeMap;
|
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
import org.alfresco.repo.transaction.TransactionalDao;
|
|
import org.alfresco.service.cmr.audit.AuditInfo;
|
|
import org.alfresco.service.cmr.repository.ContentReader;
|
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.datatype.Duration;
|
|
import org.alfresco.util.EqualsHelper;
|
|
import org.alfresco.util.GUID;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
import org.hibernate.Session;
|
|
import org.hibernate.mapping.Column;
|
|
import org.springframework.orm.hibernate3.HibernateCallback;
|
|
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
|
|
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
|
|
|
|
/**
|
|
* Assumes mimetype and encoding sent to the content store (we are not saving this anywhere)
|
|
*
|
|
* @author Andy Hind
|
|
*/
|
|
public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO, TransactionalDao
|
|
{
|
|
/**
|
|
* Logging
|
|
*/
|
|
private static Log s_logger = LogFactory.getLog(HibernateAuditDAO.class);
|
|
|
|
public static final String QUERY_LAST_AUDIT_DATE = "audit.GetLatestAuditDate";
|
|
|
|
public static final String QUERY_LAST_AUDIT_CONFIG = "audit.GetLatestAuditConfig";
|
|
|
|
public static final String QUERY_AUDIT_APP_SOURCE = "audit.GetAuditSourceByApplication";
|
|
|
|
public static final String QUERY_AUDIT_METHOD_SOURCE = "audit.GetAuditSourceByApplicationServiceMethod";
|
|
|
|
public static final String QUERY_AUDIT_APP_SOURCE_APP = "application";
|
|
|
|
public static final String QUERY_AUDIT_APP_SOURCE_SER = "service";
|
|
|
|
public static final String QUERY_AUDIT_APP_SOURCE_MET = "method";
|
|
|
|
public static final String QUERY_AUDIT_TRAIL = "audit.GetAuditTrailForNode";
|
|
|
|
public static final String QUERY_AUDIT_PROTOCOL = "protocol";
|
|
|
|
public static final String QUERY_AUDIT_STORE_ID = "store_id";
|
|
|
|
public static final String QUERY_AUDIT_NODE_ID = "node_id";
|
|
|
|
public static final String QUERY_AUDIT_NODE_REF = "nodeRef";
|
|
|
|
/** a uuid identifying this unique instance */
|
|
private String uuid;
|
|
|
|
private ContentStore contentStore;
|
|
|
|
private ThreadLocal<AuditConfiguration> auditConfiguration = new ThreadLocal<AuditConfiguration>();
|
|
|
|
private ThreadLocal<Long> auditConfigImplId = new ThreadLocal<Long>();
|
|
|
|
private ThreadLocal<Long> auditDateImplId = new ThreadLocal<Long>();
|
|
|
|
private ThreadLocal<HashMap<SourceKey, Long>> sourceIds = new ThreadLocal<HashMap<SourceKey, Long>>();
|
|
|
|
private LocalSessionFactoryBean localSessionFactory;
|
|
|
|
public HibernateAuditDAO()
|
|
{
|
|
super();
|
|
this.uuid = GUID.generate();
|
|
}
|
|
|
|
public ContentStore getContentStore()
|
|
{
|
|
return contentStore;
|
|
}
|
|
|
|
public void setContentStore(ContentStore contentStore)
|
|
{
|
|
this.contentStore = contentStore;
|
|
}
|
|
|
|
public void setLocalSessionFactory(LocalSessionFactoryBean localSessionFactory)
|
|
{
|
|
this.localSessionFactory = localSessionFactory;
|
|
}
|
|
|
|
public void audit(AuditState auditInfo)
|
|
{
|
|
if (auditInfo.getUserIdentifier() == null)
|
|
{
|
|
auditInfo.setUserIdentifier(AuthenticationUtil.getSystemUserName());
|
|
}
|
|
if (AuthenticationUtil.getCurrentUserName() == null)
|
|
{
|
|
AuthenticationUtil.setSystemUserAsCurrentUser();
|
|
try
|
|
{
|
|
audit0(auditInfo);
|
|
}
|
|
finally
|
|
{
|
|
AuthenticationUtil.clearCurrentSecurityContext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
audit0(auditInfo);
|
|
}
|
|
}
|
|
|
|
private void audit0(AuditState auditInfo)
|
|
{
|
|
// Find/Build the configuraton entry
|
|
AuditConfig auditConfig = getAuditConfig(auditInfo);
|
|
|
|
// Find/Build any dates
|
|
AuditDate auditDate = getAuditDate(auditInfo);
|
|
|
|
// Find/Build the source
|
|
AuditSource auditSource = getAuditSource(auditInfo);
|
|
|
|
// Build the new audit fact information
|
|
AuditFactImpl auditFact = new AuditFactImpl();
|
|
auditFact.setAuditConfig(auditConfig);
|
|
auditFact.setAuditDate(auditDate);
|
|
auditFact.setAuditSource(auditSource);
|
|
|
|
// Properties
|
|
|
|
Serializable[] args = auditInfo.getMethodArguments();
|
|
|
|
if (args != null)
|
|
{
|
|
int length;
|
|
switch (args.length)
|
|
{
|
|
default:
|
|
case 5:
|
|
auditFact.setArg5(getStringOrNull(args[4], getColumnLength("org.alfresco.repo.audit.hibernate.AuditFactImpl", "arg5")));
|
|
case 4:
|
|
auditFact.setArg4(getStringOrNull(args[3], getColumnLength("org.alfresco.repo.audit.hibernate.AuditFactImpl", "arg4")));
|
|
case 3:
|
|
auditFact.setArg3(getStringOrNull(args[2], getColumnLength("org.alfresco.repo.audit.hibernate.AuditFactImpl", "arg3")));
|
|
case 2:
|
|
auditFact.setArg2(getStringOrNull(args[1], getColumnLength("org.alfresco.repo.audit.hibernate.AuditFactImpl", "arg2")));
|
|
case 1:
|
|
auditFact.setArg1(getStringOrNull(args[0], getColumnLength("org.alfresco.repo.audit.hibernate.AuditFactImpl", "arg1")));
|
|
case 0:
|
|
}
|
|
}
|
|
|
|
auditFact.setClientInetAddress(auditInfo.getClientAddress() == null ? null : auditInfo.getClientAddress().toString());
|
|
auditFact.setDate(auditInfo.getDate());
|
|
auditFact.setException(auditInfo.getThrowable() == null ? null : auditInfo.getThrowable().getMessage());
|
|
auditFact.setFail(auditInfo.isFail());
|
|
auditFact.setFiltered(auditInfo.isFiltered());
|
|
auditFact.setHostInetAddress(auditInfo.getHostAddress() == null ? null : auditInfo.getHostAddress().toString());
|
|
auditFact.setMessage(auditInfo.getMessage());
|
|
auditFact.setNodeUUID(auditInfo.getKeyGUID());
|
|
auditFact.setPath(auditInfo.getPath());
|
|
auditFact.setReturnValue(auditInfo.getReturnObject() == null ? null : auditInfo.getReturnObject().toString());
|
|
// auditFact.setSerialisedURL()
|
|
auditFact.setSessionId(auditInfo.getSessionId());
|
|
if (auditInfo.getKeyStore() != null)
|
|
{
|
|
auditFact.setStoreId(auditInfo.getKeyStore().getIdentifier());
|
|
auditFact.setStoreProtocol(auditInfo.getKeyStore().getProtocol());
|
|
}
|
|
auditFact.setTransactionId(auditInfo.getTxId());
|
|
auditFact.setUserId(auditInfo.getUserIdentifier());
|
|
|
|
// Save
|
|
getSession().save(auditFact);
|
|
|
|
}
|
|
|
|
private int getColumnLength(String entityName, String propertyName)
|
|
{
|
|
int length = -1;
|
|
Iterator it = localSessionFactory.getConfiguration().getClassMapping(entityName).getProperty(propertyName).getValue().getColumnIterator();
|
|
if (it.hasNext())
|
|
{
|
|
Column col = (Column) it.next();
|
|
length = col.getLength();
|
|
}
|
|
if (s_logger.isDebugEnabled())
|
|
{
|
|
s_logger.debug(entityName + " "+propertyName+ " is of length " + length);
|
|
}
|
|
return length;
|
|
}
|
|
|
|
private String getStringOrNull(Object o, int size)
|
|
{
|
|
if (o == null)
|
|
{
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
String answer = o.toString();
|
|
if((size > -1) && (answer.length() > size))
|
|
{
|
|
answer = answer.substring(0, size);
|
|
}
|
|
return answer;
|
|
}
|
|
catch (Throwable t)
|
|
{
|
|
String answer = "Throwable in toString implementation for " + o.getClass() + " was " + t.getMessage();
|
|
if((size > -1) && (answer.length() > size))
|
|
{
|
|
answer = answer.substring(0, size);
|
|
}
|
|
return answer;
|
|
}
|
|
}
|
|
}
|
|
|
|
private AuditSource getAuditSource(AuditState auditInfo)
|
|
{
|
|
AuditSource auditSourceImpl;
|
|
|
|
SourceKey sourceKey = new SourceKey(auditInfo.getAuditApplication(), auditInfo.getAuditService(), auditInfo.getAuditMethod());
|
|
if (sourceIds.get() == null)
|
|
{
|
|
sourceIds.set(new HashMap<SourceKey, Long>());
|
|
}
|
|
Long id = sourceIds.get().get(sourceKey);
|
|
if (id != null)
|
|
{
|
|
auditSourceImpl = (AuditSource) getSession().get(AuditSourceImpl.class, id.longValue());
|
|
if (auditSourceImpl != null)
|
|
{
|
|
return auditSourceImpl;
|
|
}
|
|
}
|
|
|
|
if ((auditInfo.getAuditService() != null)
|
|
&& (auditInfo.getAuditService().length() > 0) && (auditInfo.getAuditMethod() != null) && (auditInfo.getAuditMethod().length() > 0))
|
|
{
|
|
auditSourceImpl = AuditSourceImpl.getApplicationSource(getSession(), auditInfo.getAuditApplication(), auditInfo.getAuditService(), auditInfo.getAuditMethod());
|
|
if (auditSourceImpl == null)
|
|
{
|
|
auditSourceImpl = new AuditSourceImpl();
|
|
auditSourceImpl.setApplication(auditInfo.getAuditApplication());
|
|
auditSourceImpl.setService(auditInfo.getAuditService());
|
|
auditSourceImpl.setMethod(auditInfo.getAuditMethod());
|
|
getSession().save(auditSourceImpl);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
auditSourceImpl = AuditSourceImpl.getApplicationSource(getSession(), auditInfo.getAuditApplication());
|
|
if (auditSourceImpl == null)
|
|
{
|
|
auditSourceImpl = new AuditSourceImpl();
|
|
auditSourceImpl.setApplication(auditInfo.getAuditApplication());
|
|
getSession().save(auditSourceImpl);
|
|
}
|
|
}
|
|
sourceIds.get().put(sourceKey, Long.valueOf(auditSourceImpl.getId()));
|
|
return auditSourceImpl;
|
|
}
|
|
|
|
private AuditDate getAuditDate(AuditState auditInfo)
|
|
{
|
|
Calendar cal = GregorianCalendar.getInstance();
|
|
cal.setTime(auditInfo.getDate());
|
|
cal.set(Calendar.MILLISECOND, 0);
|
|
cal.set(Calendar.SECOND, 0);
|
|
cal.set(Calendar.MINUTE, 0);
|
|
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
Date required = cal.getTime();
|
|
|
|
AuditDate auditDate;
|
|
if (auditDateImplId.get() == null)
|
|
{
|
|
auditDate = AuditDateImpl.getLatestDate(getSession());
|
|
if (auditDate == null)
|
|
{
|
|
// The first entry ever so we just make it
|
|
auditDate = new AuditDateImpl(auditInfo.getDate());
|
|
getSession().save(auditDate);
|
|
}
|
|
auditDateImplId.set(Long.valueOf(auditDate.getId()));
|
|
}
|
|
else
|
|
{
|
|
auditDate = (AuditDate) getSession().get(AuditDateImpl.class, auditDateImplId.get().longValue());
|
|
if ((auditDate == null) || (!required.equals(auditDate.getDate())))
|
|
{
|
|
auditDate = AuditDateImpl.getLatestDate(getSession());
|
|
if (auditDate == null)
|
|
{
|
|
// The first entry ever so we just make it
|
|
auditDate = new AuditDateImpl(auditInfo.getDate());
|
|
getSession().save(auditDate);
|
|
}
|
|
auditDateImplId.set(Long.valueOf(auditDate.getId()));
|
|
}
|
|
}
|
|
while (!required.equals(auditDate.getDate()))
|
|
{
|
|
Date nextDate = Duration.add(auditDate.getDate(), new Duration("P1D"));
|
|
auditDate = new AuditDateImpl(nextDate);
|
|
getSession().save(auditDate);
|
|
auditDateImplId.set(Long.valueOf(auditDate.getId()));
|
|
}
|
|
return auditDate;
|
|
}
|
|
|
|
private AuditConfig getAuditConfig(AuditState auditInfo)
|
|
{
|
|
AuditConfig auditConfig;
|
|
if ((auditConfiguration.get() == null) || (auditConfiguration.get() != auditInfo.getAuditConfiguration()))
|
|
{
|
|
auditConfig = AuditConfigImpl.getLatestConfig(getSession());
|
|
if (auditConfig == null)
|
|
{
|
|
auditConfig = createNewAuditConfigImpl(auditInfo);
|
|
}
|
|
else
|
|
{
|
|
InputStream current = new BufferedInputStream(auditInfo.getAuditConfiguration().getInputStream());
|
|
ContentReader reader = contentStore.getReader(auditConfig.getConfigURL());
|
|
reader.setMimetype(MimetypeMap.MIMETYPE_XML);
|
|
reader.setEncoding("UTF-8");
|
|
InputStream last = new BufferedInputStream(reader.getContentInputStream());
|
|
int currentValue = -2;
|
|
int lastValue = -2;
|
|
try
|
|
{
|
|
while ((currentValue != -1) && (lastValue != -1) && (currentValue == lastValue))
|
|
{
|
|
currentValue = current.read();
|
|
lastValue = last.read();
|
|
|
|
}
|
|
}
|
|
catch (IOException e)
|
|
{
|
|
throw new AlfrescoRuntimeException("Failed to read and validate current audit configuration against the last", e);
|
|
}
|
|
if (currentValue != lastValue)
|
|
{
|
|
// Files are different - require a new entry
|
|
auditConfig = createNewAuditConfigImpl(auditInfo);
|
|
}
|
|
else
|
|
{
|
|
// No change
|
|
}
|
|
}
|
|
auditConfigImplId.set(Long.valueOf(auditConfig.getId()));
|
|
auditConfiguration.set(auditInfo.getAuditConfiguration());
|
|
}
|
|
else
|
|
{
|
|
auditConfig = (AuditConfig) getSession().get(AuditConfigImpl.class, auditConfigImplId.get().longValue());
|
|
if (auditConfig == null)
|
|
{
|
|
auditConfig = createNewAuditConfigImpl(auditInfo);
|
|
}
|
|
}
|
|
return auditConfig;
|
|
}
|
|
|
|
private AuditConfigImpl createNewAuditConfigImpl(AuditState auditInfo)
|
|
{
|
|
AuditConfigImpl auditConfig = new AuditConfigImpl();
|
|
InputStream is = new BufferedInputStream(auditInfo.getAuditConfiguration().getInputStream());
|
|
ContentWriter writer = contentStore.getWriter(ContentStore.NEW_CONTENT_CONTEXT);
|
|
writer.setMimetype(MimetypeMap.MIMETYPE_XML);
|
|
writer.setEncoding("UTF-8");
|
|
writer.putContent(is);
|
|
String contentUrl = writer.getContentUrl();
|
|
auditConfig.setConfigURL(contentUrl);
|
|
getSession().save(auditConfig);
|
|
return auditConfig;
|
|
}
|
|
|
|
/**
|
|
* Checks equality by type and uuid
|
|
*/
|
|
public boolean equals(Object obj)
|
|
{
|
|
if (obj == null)
|
|
{
|
|
return false;
|
|
}
|
|
else if (!(obj instanceof HibernateAuditDAO))
|
|
{
|
|
return false;
|
|
}
|
|
HibernateAuditDAO that = (HibernateAuditDAO) obj;
|
|
return this.uuid.equals(that.uuid);
|
|
}
|
|
|
|
/**
|
|
* @see #uuid
|
|
*/
|
|
public int hashCode()
|
|
{
|
|
return uuid.hashCode();
|
|
}
|
|
|
|
/**
|
|
* Does this <tt>Session</tt> contain any changes which must be synchronized with the store?
|
|
*
|
|
* @return true => changes are pending
|
|
*/
|
|
public boolean isDirty()
|
|
{
|
|
// create a callback for the task
|
|
HibernateCallback callback = new HibernateCallback()
|
|
{
|
|
public Object doInHibernate(Session session)
|
|
{
|
|
return session.isDirty();
|
|
}
|
|
};
|
|
// execute the callback
|
|
return ((Boolean) getHibernateTemplate().execute(callback)).booleanValue();
|
|
}
|
|
|
|
/**
|
|
* Just flushes the session
|
|
*/
|
|
public void flush()
|
|
{
|
|
getSession().flush();
|
|
}
|
|
|
|
static class SourceKey
|
|
{
|
|
String application;
|
|
|
|
String service;
|
|
|
|
String method;
|
|
|
|
SourceKey(String application, String service, String method)
|
|
{
|
|
this.application = application;
|
|
this.service = service;
|
|
this.method = method;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o)
|
|
{
|
|
if (this == o)
|
|
{
|
|
return true;
|
|
}
|
|
if (!(this instanceof SourceKey))
|
|
{
|
|
return false;
|
|
}
|
|
SourceKey other = (SourceKey) o;
|
|
return EqualsHelper.nullSafeEquals(this.application, other.application)
|
|
&& EqualsHelper.nullSafeEquals(this.service, other.service) && EqualsHelper.nullSafeEquals(this.method, other.method);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode()
|
|
{
|
|
int hash = application.hashCode();
|
|
if (service != null)
|
|
{
|
|
hash = (hash * 37) + service.hashCode();
|
|
}
|
|
if (method != null)
|
|
{
|
|
hash = (hash * 37) + method.hashCode();
|
|
}
|
|
return hash;
|
|
}
|
|
}
|
|
|
|
public List<AuditInfo> getAuditTrail(NodeRef nodeRef)
|
|
{
|
|
if (nodeRef == null)
|
|
{
|
|
return Collections.<AuditInfo> emptyList();
|
|
}
|
|
List<? extends AuditFact> internalTrail = AuditFactImpl.getAuditTrail(getSession(), nodeRef);
|
|
|
|
ArrayList<AuditInfo> answer = new ArrayList<AuditInfo>(internalTrail.size());
|
|
for (AuditFact auditFact : internalTrail)
|
|
{
|
|
AuditInfo info = new AuditInfoImpl(auditFact);
|
|
answer.add(info);
|
|
}
|
|
return answer;
|
|
}
|
|
|
|
}
|