mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Audit changes and fixes
- Removed notion of audit session - Removed 'scope' attribute for DataGenerator elements - Removed alf_audit_session table and replaced with alf_audit_app (see script) - DataGenerators are working properly git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16053 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -79,7 +79,6 @@
|
|||||||
<xs:complexContent>
|
<xs:complexContent>
|
||||||
<xs:extension base="a:KeyedAuditDefinition">
|
<xs:extension base="a:KeyedAuditDefinition">
|
||||||
<xs:attribute name="dataGenerator" type="a:NameAttribute" use="required" />
|
<xs:attribute name="dataGenerator" type="a:NameAttribute" use="required" />
|
||||||
<xs:attribute name="scope" type="a:ScopeAttribute" use="required" />
|
|
||||||
</xs:extension>
|
</xs:extension>
|
||||||
</xs:complexContent>
|
</xs:complexContent>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
@@ -114,12 +113,4 @@
|
|||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
|
|
||||||
<xs:simpleType name="ScopeAttribute">
|
|
||||||
<xs:restriction base="xs:string">
|
|
||||||
<xs:enumeration value="SESSION"/>
|
|
||||||
<xs:enumeration value="AUDIT"/>
|
|
||||||
<xs:enumeration value="ALL"/>
|
|
||||||
</xs:restriction>
|
|
||||||
</xs:simpleType>
|
|
||||||
|
|
||||||
</xs:schema>
|
</xs:schema>
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
<Application name="Alfresco Repository" key="repository">
|
<Application name="Alfresco Repository" key="repository">
|
||||||
<AuditPath key="services">
|
<AuditPath key="services">
|
||||||
<GenerateValue key="txn" dataGenerator="transactionId" scope="AUDIT"/>
|
<GenerateValue key="txn" dataGenerator="transactionId"/>
|
||||||
<AuditPath key="nodeservice">
|
<AuditPath key="nodeservice">
|
||||||
<AuditPath key="createstore">
|
<AuditPath key="createstore">
|
||||||
<AuditPath key="protocol">
|
<AuditPath key="protocol">
|
||||||
|
@@ -17,24 +17,24 @@ CREATE TABLE alf_audit_model
|
|||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
) ENGINE=InnoDB;
|
) ENGINE=InnoDB;
|
||||||
|
|
||||||
CREATE TABLE alf_audit_session
|
CREATE TABLE alf_audit_app
|
||||||
(
|
(
|
||||||
id BIGINT NOT NULL AUTO_INCREMENT,
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
audit_model_id BIGINT NOT NULL,
|
audit_model_id BIGINT NOT NULL,
|
||||||
app_name_id BIGINT NOT NULL,
|
app_name_id BIGINT NOT NULL,
|
||||||
CONSTRAINT fk_alf_audit_sess_model FOREIGN KEY (audit_model_id) REFERENCES alf_audit_model (id),
|
CONSTRAINT fk_alf_audit_app_model FOREIGN KEY (audit_model_id) REFERENCES alf_audit_model (id) ON DELETE CASCADE,
|
||||||
CONSTRAINT fk_alf_audit_sess_app FOREIGN KEY (app_name_id) REFERENCES alf_prop_value (id),
|
CONSTRAINT fk_alf_audit_app_app FOREIGN KEY (app_name_id) REFERENCES alf_prop_value (id),
|
||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
) ENGINE=InnoDB;
|
) ENGINE=InnoDB;
|
||||||
|
|
||||||
CREATE TABLE alf_audit_entry
|
CREATE TABLE alf_audit_entry
|
||||||
(
|
(
|
||||||
id BIGINT NOT NULL AUTO_INCREMENT,
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
audit_session_id BIGINT NOT NULL,
|
audit_app_id BIGINT NOT NULL,
|
||||||
audit_time BIGINT NOT NULL,
|
audit_time BIGINT NOT NULL,
|
||||||
audit_user_id BIGINT NULL,
|
audit_user_id BIGINT NULL,
|
||||||
audit_values_id BIGINT NULL,
|
audit_values_id BIGINT NULL,
|
||||||
CONSTRAINT fk_alf_audit_ent_sess FOREIGN KEY (audit_session_id) REFERENCES alf_audit_session (id),
|
CONSTRAINT fk_alf_audit_ent_app FOREIGN KEY (audit_app_id) REFERENCES alf_audit_app (id) ON DELETE CASCADE,
|
||||||
INDEX idx_alf_audit_ent_time (audit_time),
|
INDEX idx_alf_audit_ent_time (audit_time),
|
||||||
CONSTRAINT fk_alf_audit_ent_user FOREIGN KEY (audit_user_id) REFERENCES alf_prop_value (id),
|
CONSTRAINT fk_alf_audit_ent_user FOREIGN KEY (audit_user_id) REFERENCES alf_prop_value (id),
|
||||||
CONSTRAINT fk_alf_audit_ent_prop FOREIGN KEY (audit_values_id) REFERENCES alf_prop_value (id),
|
CONSTRAINT fk_alf_audit_ent_prop FOREIGN KEY (audit_values_id) REFERENCES alf_prop_value (id),
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
<!-- -->
|
<!-- -->
|
||||||
|
|
||||||
<typeAlias alias="AuditModel" type="org.alfresco.repo.domain.audit.AuditModelEntity"/>
|
<typeAlias alias="AuditModel" type="org.alfresco.repo.domain.audit.AuditModelEntity"/>
|
||||||
<typeAlias alias="AuditSession" type="org.alfresco.repo.domain.audit.AuditSessionEntity"/>
|
<typeAlias alias="AuditApplication" type="org.alfresco.repo.domain.audit.AuditApplicationEntity"/>
|
||||||
<typeAlias alias="AuditEntry" type="org.alfresco.repo.domain.audit.AuditEntryEntity"/>
|
<typeAlias alias="AuditEntry" type="org.alfresco.repo.domain.audit.AuditEntryEntity"/>
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
@@ -23,14 +23,14 @@
|
|||||||
<result property="contentDataId" column="content_data_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="contentDataId" column="content_data_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
<result property="contentCrc" column="content_crc" jdbcType="BIGINT" javaType="long"/>
|
<result property="contentCrc" column="content_crc" jdbcType="BIGINT" javaType="long"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<resultMap id="result.AuditSession" class="AuditSession">
|
<resultMap id="result.AuditApplication" class="AuditApplication">
|
||||||
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
<result property="auditModelId" column="audit_model_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="auditModelId" column="audit_model_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
<result property="applicationNameId" column="app_name_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="applicationNameId" column="app_name_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
<resultMap id="result.AuditEntry" class="AuditEntry">
|
<resultMap id="result.AuditEntry" class="AuditEntry">
|
||||||
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
<result property="auditSessionId" column="audit_session_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="auditApplicationId" column="audit_app_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
<result property="auditUserId" column="audit_user_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="auditUserId" column="audit_user_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
<result property="auditTime" column="audit_time" jdbcType="BIGINT" javaType="long"/>
|
<result property="auditTime" column="audit_time" jdbcType="BIGINT" javaType="long"/>
|
||||||
<result property="auditValuesId" column="audit_values_id" jdbcType="BIGINT" javaType="long"/>
|
<result property="auditValuesId" column="audit_values_id" jdbcType="BIGINT" javaType="long"/>
|
||||||
@@ -53,14 +53,14 @@
|
|||||||
values (#contentDataId#, #contentCrc#)
|
values (#contentDataId#, #contentCrc#)
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<sql id="insert.AuditSession.AutoIncrement">
|
<sql id="insert.AuditApplication.AutoIncrement">
|
||||||
insert into alf_audit_session (audit_model_id, app_name_id)
|
insert into alf_audit_app (audit_model_id, app_name_id)
|
||||||
values (#auditModelId#, #applicationNameId#)
|
values (#auditModelId#, #applicationNameId#)
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<sql id="insert.AuditEntry.AutoIncrement">
|
<sql id="insert.AuditEntry.AutoIncrement">
|
||||||
insert into alf_audit_entry (audit_session_id, audit_user_id, audit_time, audit_values_id)
|
insert into alf_audit_entry (audit_app_id, audit_user_id, audit_time, audit_values_id)
|
||||||
values (#auditSessionId#, #auditUserId#, #auditTime#, #auditValuesId#)
|
values (#auditApplicationId#, #auditUserId#, #auditTime#, #auditValuesId#)
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
@@ -77,4 +77,14 @@
|
|||||||
content_crc = #contentCrc#
|
content_crc = #contentCrc#
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- Get the audit application by model ID -->
|
||||||
|
<select id="select.AuditApplicationByModelId" parameterMap="parameter.IdMap" resultMap="result.AuditApplication">
|
||||||
|
select
|
||||||
|
*
|
||||||
|
from
|
||||||
|
alf_audit_app
|
||||||
|
where
|
||||||
|
audit_model_id = ?
|
||||||
|
</select>
|
||||||
|
|
||||||
</sqlMap>
|
</sqlMap>
|
@@ -13,8 +13,8 @@
|
|||||||
</selectKey>
|
</selectKey>
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<insert id="insert.AuditSession" parameterClass="AuditSession" >
|
<insert id="insert.AuditApplication" parameterClass="AuditApplication" >
|
||||||
<include refid="insert.AuditSession.AutoIncrement"/>
|
<include refid="insert.AuditApplication.AutoIncrement"/>
|
||||||
<selectKey resultClass="long" keyProperty="id" type="post">
|
<selectKey resultClass="long" keyProperty="id" type="post">
|
||||||
KEY_COLUMN:GENERATED_KEY
|
KEY_COLUMN:GENERATED_KEY
|
||||||
</selectKey>
|
</selectKey>
|
||||||
|
@@ -31,7 +31,6 @@ import junit.framework.TestCase;
|
|||||||
|
|
||||||
import org.alfresco.repo.audit.extractor.DataExtractor;
|
import org.alfresco.repo.audit.extractor.DataExtractor;
|
||||||
import org.alfresco.repo.audit.generator.DataGenerator;
|
import org.alfresco.repo.audit.generator.DataGenerator;
|
||||||
import org.alfresco.repo.audit.generator.DataGenerator.DataGeneratorScope;
|
|
||||||
import org.alfresco.repo.audit.model.AuditApplication;
|
import org.alfresco.repo.audit.model.AuditApplication;
|
||||||
import org.alfresco.repo.audit.model.AuditModelException;
|
import org.alfresco.repo.audit.model.AuditModelException;
|
||||||
import org.alfresco.repo.audit.model.AuditModelRegistry;
|
import org.alfresco.repo.audit.model.AuditModelRegistry;
|
||||||
@@ -110,7 +109,7 @@ public class AuditBootstrapTest extends TestCase
|
|||||||
loadBadModel("classpath:alfresco/audit/alfresco-audit-test-bad-04.xml");
|
loadBadModel("classpath:alfresco/audit/alfresco-audit-test-bad-04.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testModelLoading_InvalidScope() throws Exception
|
public void testModelLoading_InvalidDataGeneratorName() throws Exception
|
||||||
{
|
{
|
||||||
loadBadModel("classpath:alfresco/audit/alfresco-audit-test-bad-05.xml");
|
loadBadModel("classpath:alfresco/audit/alfresco-audit-test-bad-05.xml");
|
||||||
}
|
}
|
||||||
@@ -120,10 +119,10 @@ public class AuditBootstrapTest extends TestCase
|
|||||||
loadBadModel("classpath:alfresco/audit/alfresco-audit-test-bad-06.xml");
|
loadBadModel("classpath:alfresco/audit/alfresco-audit-test-bad-06.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetModelId()
|
public void testGetApplicationId()
|
||||||
{
|
{
|
||||||
Long repoId = auditModelRegistry.getAuditModelId(APPLICATION_TEST);
|
Long appId = auditModelRegistry.getAuditApplicationId(APPLICATION_TEST);
|
||||||
assertNotNull("No audit model ID for " + APPLICATION_TEST, repoId);
|
assertNotNull("No audit application ID for " + APPLICATION_TEST, appId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testBadPath(AuditApplication app, String path)
|
private void testBadPath(AuditApplication app, String path)
|
||||||
@@ -162,32 +161,32 @@ public class AuditBootstrapTest extends TestCase
|
|||||||
assertTrue("Expected no extractors", extractors.isEmpty());
|
assertTrue("Expected no extractors", extractors.isEmpty());
|
||||||
|
|
||||||
extractors = app.getDataExtractors("/test/1.1/2.1/3.1/4.1");
|
extractors = app.getDataExtractors("/test/1.1/2.1/3.1/4.1");
|
||||||
assertEquals(2, extractors.size());
|
assertEquals(1, extractors.size());
|
||||||
assertTrue(extractors.containsKey("/test/1.1/2.1/3.1/value.1"));
|
|
||||||
assertTrue(extractors.containsKey("/test/1.1/2.1/3.1/4.1/value.1"));
|
assertTrue(extractors.containsKey("/test/1.1/2.1/3.1/4.1/value.1"));
|
||||||
|
|
||||||
|
extractors = app.getDataExtractors("/test/1.1/2.1/3.1");
|
||||||
|
assertEquals(1, extractors.size());
|
||||||
|
assertTrue(extractors.containsKey("/test/1.1/2.1/3.1/value.1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuditApplication_GetDataGenerators_AnyScope()
|
public void testAuditApplication_GetDataGenerators()
|
||||||
{
|
{
|
||||||
AuditApplication app = auditModelRegistry.getAuditApplication(APPLICATION_TEST);
|
AuditApplication app = auditModelRegistry.getAuditApplication(APPLICATION_TEST);
|
||||||
assertNotNull(app);
|
assertNotNull(app);
|
||||||
|
|
||||||
Map<String, DataGenerator> generators = app.getDataGenerators("/blah", DataGeneratorScope.ALL);
|
Map<String, DataGenerator> generators = app.getDataGenerators("/blah");
|
||||||
assertNotNull("Should never get a null map", generators);
|
assertNotNull("Should never get a null map", generators);
|
||||||
assertTrue("Expected no generators", generators.isEmpty());
|
assertTrue("Expected no generators", generators.isEmpty());
|
||||||
|
|
||||||
generators = app.getDataGenerators("/test/1.1/2.1/3.1/4.1", DataGeneratorScope.ALL);
|
generators = app.getDataGenerators("/test/1.1/2.1/3.1/4.1");
|
||||||
assertEquals(1, generators.size());
|
assertEquals(1, generators.size());
|
||||||
assertTrue(generators.containsKey("/test/time"));
|
assertTrue(generators.containsKey("/test/time"));
|
||||||
|
|
||||||
generators = app.getDataGenerators("/test/1.1/2.1/3.1/4.1", DataGeneratorScope.SESSION);
|
generators = app.getDataGenerators("/test/1.1/2.1/3.1/4.1");
|
||||||
assertEquals(1, generators.size());
|
assertEquals(1, generators.size());
|
||||||
assertTrue(generators.containsKey("/test/time"));
|
assertTrue(generators.containsKey("/test/time"));
|
||||||
|
|
||||||
generators = app.getDataGenerators("/test/1.1/2.1/3.1/4.1", DataGeneratorScope.AUDIT);
|
generators = app.getDataGenerators("/test/1.1/2.2/3.2/4.1");
|
||||||
assertEquals(0, generators.size());
|
|
||||||
|
|
||||||
generators = app.getDataGenerators("/test/1.1/2.2/3.2/4.1", DataGeneratorScope.ALL);
|
|
||||||
assertEquals(2, generators.size());
|
assertEquals(2, generators.size());
|
||||||
assertTrue(generators.containsKey("/test/time"));
|
assertTrue(generators.containsKey("/test/time"));
|
||||||
assertTrue(generators.containsKey("/test/1.1/2.2/3.2/4.1/time"));
|
assertTrue(generators.containsKey("/test/1.1/2.2/3.2/4.1/time"));
|
||||||
|
@@ -83,38 +83,6 @@ public interface AuditComponent
|
|||||||
* V3.2 from here on. Put all fixes to the older audit code before this point, please.
|
* V3.2 from here on. Put all fixes to the older audit code before this point, please.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Start an audit session for the given root path. All later audit values must start with
|
|
||||||
* the same root path.
|
|
||||||
* <p/>
|
|
||||||
* The name of the application controls part of the audit model will be used. The root path must
|
|
||||||
* start with the path separator '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR}) and the matching
|
|
||||||
* <b>key</b> attribute that was declared for the <b>Application</b> element in the audit configuration.
|
|
||||||
* <p/>
|
|
||||||
* This is a read-write method. Client code must wrap calls in the appropriate transactional wrappers.
|
|
||||||
*
|
|
||||||
* @param applicationName the name of the application to log against
|
|
||||||
* @param rootPath a base path of {@link AuditPath} key entries concatenated with
|
|
||||||
* {@link AuditApplication#AUDIT_PATH_SEPARATOR}.
|
|
||||||
* @return Returns the unique session or <tt>null</tt> if no session was created
|
|
||||||
* @throws IllegalStateException if there is not a writable transaction present
|
|
||||||
*/
|
|
||||||
AuditSession startAuditSession(String applicationName, String rootPath);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc AuditComponent#startAuditSession(String, String)}
|
|
||||||
|
|
||||||
* @param applicationName the name of the application to log against
|
|
||||||
* @param rootPath a base path of {@link AuditPath} key entries concatenated with the path separator
|
|
||||||
* '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR})
|
|
||||||
* @param values values to associate with the session. These values will override or
|
|
||||||
* complement generated session-specific values
|
|
||||||
* @param rootPath a base path of {@link AuditPath} key entries concatenated with
|
|
||||||
* {@link AuditApplication#AUDIT_PATH_SEPARATOR}.
|
|
||||||
* @throws IllegalStateException if there is not a writable transaction present
|
|
||||||
*/
|
|
||||||
AuditSession startAuditSession(String applicationName, String rootPath, Map<String, Serializable> values);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record a set of values against the given session. The map is a path - starting with '/'
|
* Record a set of values against the given session. The map is a path - starting with '/'
|
||||||
* ({@link AuditApplication#AUDIT_PATH_SEPARATOR}), relative to the root path given when
|
* ({@link AuditApplication#AUDIT_PATH_SEPARATOR}), relative to the root path given when
|
||||||
@@ -126,9 +94,11 @@ public interface AuditComponent
|
|||||||
* <p/>
|
* <p/>
|
||||||
* This is a read-write method. Client code must wrap calls in the appropriate transactional wrappers.
|
* This is a read-write method. Client code must wrap calls in the appropriate transactional wrappers.
|
||||||
*
|
*
|
||||||
* @param session a pre-existing audit session to continue with
|
* @param applicationName the name of the application to log against
|
||||||
* @param values the values to audit mapped by {@link AuditPath} key relative to the session
|
* @param rootPath a base path of {@link AuditPath} key entries concatenated with the path separator
|
||||||
* root path
|
* '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR})
|
||||||
|
* @param values the values to audit mapped by {@link AuditPath} key relative to root path
|
||||||
|
* (may be <tt>null</tt>)
|
||||||
* @return Returns the values that were actually persisted, keyed by their full path.
|
* @return Returns the values that were actually persisted, keyed by their full path.
|
||||||
* @throws IllegalStateException if there is not a writable transaction present
|
* @throws IllegalStateException if there is not a writable transaction present
|
||||||
*
|
*
|
||||||
@@ -136,5 +106,5 @@ public interface AuditComponent
|
|||||||
*
|
*
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
Map<String, Serializable> audit(AuditSession session, Map<String, Serializable> values);
|
Map<String, Serializable> audit(String applicationName, String rootPath, Map<String, Serializable> values);
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@ import java.io.Serializable;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -35,7 +36,6 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.alfresco.repo.audit.extractor.DataExtractor;
|
import org.alfresco.repo.audit.extractor.DataExtractor;
|
||||||
import org.alfresco.repo.audit.generator.DataGenerator;
|
import org.alfresco.repo.audit.generator.DataGenerator;
|
||||||
import org.alfresco.repo.audit.generator.DataGenerator.DataGeneratorScope;
|
|
||||||
import org.alfresco.repo.audit.model.AuditApplication;
|
import org.alfresco.repo.audit.model.AuditApplication;
|
||||||
import org.alfresco.repo.audit.model.AuditEntry;
|
import org.alfresco.repo.audit.model.AuditEntry;
|
||||||
import org.alfresco.repo.audit.model.AuditModelRegistry;
|
import org.alfresco.repo.audit.model.AuditModelRegistry;
|
||||||
@@ -767,27 +767,25 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
this.auditModelRegistry = auditModelRegistry;
|
this.auditModelRegistry = auditModelRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #startAuditSession(String, String, Map)
|
|
||||||
* @since 3.2
|
|
||||||
*/
|
|
||||||
public AuditSession startAuditSession(String applicationName, String rootPath)
|
|
||||||
{
|
|
||||||
return startAuditSession(applicationName, rootPath, new HashMap<String, Serializable>(11));
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public AuditSession startAuditSession(String applicationName, String rootPath, Map<String, Serializable> values)
|
public Map<String, Serializable> audit(String applicationName, String rootPath, Map<String, Serializable> values)
|
||||||
{
|
{
|
||||||
ParameterCheck.mandatory("applicationName", applicationName);
|
ParameterCheck.mandatory("applicationName", applicationName);
|
||||||
ParameterCheck.mandatory("values", values);
|
ParameterCheck.mandatory("rootPath", rootPath);
|
||||||
|
|
||||||
if (AlfrescoTransactionSupport.getTransactionReadState() != TxnReadState.TXN_READ_WRITE)
|
if (AlfrescoTransactionSupport.getTransactionReadState() != TxnReadState.TXN_READ_WRITE)
|
||||||
{
|
{
|
||||||
throw new IllegalStateException("Auditing requires a read-write transaction.");
|
throw new IllegalStateException("Auditing requires a read-write transaction.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (values == null)
|
||||||
|
{
|
||||||
|
values = Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
// Get the application
|
// Get the application
|
||||||
AuditApplication application = auditModelRegistry.getAuditApplication(applicationName);
|
AuditApplication application = auditModelRegistry.getAuditApplication(applicationName);
|
||||||
if (application == null)
|
if (application == null)
|
||||||
@@ -796,61 +794,19 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
{
|
{
|
||||||
logger.debug("No audit application named '" + applicationName + "' has been registered.");
|
logger.debug("No audit application named '" + applicationName + "' has been registered.");
|
||||||
}
|
}
|
||||||
return null;
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
// Check the path against the application
|
// Check the path against the application
|
||||||
application.checkPath(rootPath);
|
application.checkPath(rootPath);
|
||||||
// Get the model ID for the application
|
// Get the model ID for the application
|
||||||
Long modelId = auditModelRegistry.getAuditModelId(applicationName);
|
Long applicationId = auditModelRegistry.getAuditApplicationId(applicationName);
|
||||||
if (modelId == null)
|
if (applicationId == null)
|
||||||
{
|
{
|
||||||
throw new AuditException("No model exists for audit application: " + applicationName);
|
throw new AuditException("No persisted instance exists for audit application: " + applicationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now create the session
|
// TODO: Check if the root path is enabled or not
|
||||||
Long sessionId = auditDAO.createAuditSession(modelId, applicationName);
|
|
||||||
AuditSession session = new AuditSession(application, rootPath, sessionId);
|
|
||||||
|
|
||||||
// Generate session data
|
|
||||||
Map<String, DataGenerator> generators = application.getDataGenerators(rootPath, DataGeneratorScope.SESSION);
|
|
||||||
Map<String, Serializable> sessionData = generateData(generators);
|
|
||||||
|
|
||||||
// Extract data from the values passed in
|
|
||||||
Map<String, Serializable> extractedData = extractData(application, values);
|
|
||||||
|
|
||||||
// Combine the values
|
|
||||||
Map<String, Serializable> allData = new HashMap<String, Serializable>(sessionData);
|
|
||||||
allData.putAll(extractedData);
|
|
||||||
|
|
||||||
// Audit it
|
|
||||||
audit(session, allData);
|
|
||||||
|
|
||||||
// Done
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("New audit session: " + session);
|
|
||||||
}
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
* @since 3.2
|
|
||||||
*/
|
|
||||||
public Map<String, Serializable> audit(AuditSession session, Map<String, Serializable> values)
|
|
||||||
{
|
|
||||||
ParameterCheck.mandatory("session", session);
|
|
||||||
ParameterCheck.mandatory("values", values);
|
|
||||||
|
|
||||||
if (AlfrescoTransactionSupport.getTransactionReadState() != TxnReadState.TXN_READ_WRITE)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException("Auditing requires a read-write transaction.");
|
|
||||||
}
|
|
||||||
|
|
||||||
AuditApplication app = session.getApplication();
|
|
||||||
String rootPath = session.getRootPath();
|
|
||||||
Long sessionId = session.getSessionId();
|
|
||||||
|
|
||||||
// Build the key paths using the session root path
|
// Build the key paths using the session root path
|
||||||
Map<String, Serializable> pathedValues = new HashMap<String, Serializable>(values.size() * 2);
|
Map<String, Serializable> pathedValues = new HashMap<String, Serializable>(values.size() * 2);
|
||||||
for (Map.Entry<String, Serializable> entry : values.entrySet())
|
for (Map.Entry<String, Serializable> entry : values.entrySet())
|
||||||
@@ -860,27 +816,38 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
pathedValues.put(path, entry.getValue());
|
pathedValues.put(path, entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate data
|
||||||
|
Map<String, DataGenerator> generators = application.getDataGenerators(pathedValues.keySet());
|
||||||
|
Map<String, Serializable> auditData = generateData(generators);
|
||||||
|
|
||||||
// Now extract values
|
// Now extract values
|
||||||
Map<String, Serializable> extractedValues = extractData(app, pathedValues);
|
Map<String, Serializable> extractedData = extractData(application, pathedValues);
|
||||||
|
|
||||||
|
// Combine extracted and generated values (extracted data takes precedence)
|
||||||
|
auditData.putAll(extractedData);
|
||||||
|
|
||||||
// Time and username are intrinsic
|
// Time and username are intrinsic
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
String username = AuthenticationUtil.getFullyAuthenticatedUser();
|
String username = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||||
|
|
||||||
// Persist the values
|
Long entryId = null;
|
||||||
Long entryId = auditDAO.createAuditEntry(sessionId, time, username, pathedValues);
|
if (!auditData.isEmpty())
|
||||||
|
{
|
||||||
|
// Persist the values
|
||||||
|
entryId = auditDAO.createAuditEntry(applicationId, time, username, auditData);
|
||||||
|
}
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"New audit entry: \n" +
|
"New audit entry: \n" +
|
||||||
" Session ID: " + sessionId + "\n" +
|
" Applicatoin ID: " + applicationId + "\n" +
|
||||||
" Entry ID: " + entryId + "\n" +
|
" Entry ID: " + entryId + "\n" +
|
||||||
" Path Values: " + pathedValues + "\n" +
|
" Path Values: " + pathedValues + "\n" +
|
||||||
" Extracted Values: " + extractedValues);
|
" Audit Data: " + auditData);
|
||||||
}
|
}
|
||||||
return extractedValues;
|
return auditData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -110,11 +110,11 @@ public class AuditComponentTest extends TestCase
|
|||||||
// Just here to fail if the basic startup fails
|
// Just here to fail if the basic startup fails
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testStartSessionWithBadPath() throws Exception
|
public void testAuditWithBadPath() throws Exception
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auditComponent.startAuditSession(APPLICATION_TEST, "test");
|
auditComponent.audit(APPLICATION_TEST, "/test", null);
|
||||||
fail("Should fail due to lack of a transaction.");
|
fail("Should fail due to lack of a transaction.");
|
||||||
}
|
}
|
||||||
catch (IllegalStateException e)
|
catch (IllegalStateException e)
|
||||||
@@ -127,7 +127,7 @@ public class AuditComponentTest extends TestCase
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auditComponent.startAuditSession(APPLICATION_TEST, "test");
|
auditComponent.audit(APPLICATION_TEST, "test", null);
|
||||||
fail("Failed to detect illegal path");
|
fail("Failed to detect illegal path");
|
||||||
}
|
}
|
||||||
catch (AuditModelException e)
|
catch (AuditModelException e)
|
||||||
@@ -136,18 +136,16 @@ public class AuditComponentTest extends TestCase
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auditComponent.startAuditSession(APPLICATION_TEST, "/test/");
|
auditComponent.audit(APPLICATION_TEST, "/test/", null);
|
||||||
fail("Failed to detect illegal path");
|
fail("Failed to detect illegal path");
|
||||||
}
|
}
|
||||||
catch (AuditModelException e)
|
catch (AuditModelException e)
|
||||||
{
|
{
|
||||||
// Expected
|
// Expected
|
||||||
}
|
}
|
||||||
AuditSession session;
|
Map<String, Serializable> auditedValues = auditComponent.audit("Bogus App", "/test", null);
|
||||||
session = auditComponent.startAuditSession("Bogus App", "/test");
|
assertNotNull(auditedValues);
|
||||||
assertNull("Invalid app should return null session.", session);
|
assertTrue("Invalid application should not audit anything", auditedValues.isEmpty());
|
||||||
session = auditComponent.startAuditSession(APPLICATION_TEST, "/test");
|
|
||||||
assertNotNull("Valid app and root path failed to create session.", session);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -158,20 +156,18 @@ public class AuditComponentTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* Start a session and use it within a single txn
|
* Start a session and use it within a single txn
|
||||||
*/
|
*/
|
||||||
public void testSession_Basic() throws Exception
|
public void testAudit_Basic() throws Exception
|
||||||
{
|
{
|
||||||
final RetryingTransactionCallback<Void> testCallback = new RetryingTransactionCallback<Void>()
|
final RetryingTransactionCallback<Void> testCallback = new RetryingTransactionCallback<Void>()
|
||||||
{
|
{
|
||||||
public Void execute() throws Throwable
|
public Void execute() throws Throwable
|
||||||
{
|
{
|
||||||
AuditSession session = auditComponent.startAuditSession(APPLICATION_TEST, "/test/1.1");
|
|
||||||
|
|
||||||
Map<String, Serializable> values = new HashMap<String, Serializable>(13);
|
Map<String, Serializable> values = new HashMap<String, Serializable>(13);
|
||||||
values.put("/test/1.1/2.1/3.1/4.1", new Long(41));
|
values.put("/test/1.1/2.1/3.1/4.1", new Long(41));
|
||||||
values.put("/test/1.1/2.1/3.1/4.2", "42");
|
values.put("/test/1.1/2.1/3.1/4.2", "42");
|
||||||
values.put("/test/1.1/2.1/3.1/4.2", new Date());
|
values.put("/test/1.1/2.1/3.1/4.2", new Date());
|
||||||
|
|
||||||
auditComponent.audit(session, values);
|
auditComponent.audit(APPLICATION_TEST, "/test/1.1", values);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -198,7 +194,7 @@ public class AuditComponentTest extends TestCase
|
|||||||
for (Map.Entry<String, Serializable> entry : parameters.entrySet())
|
for (Map.Entry<String, Serializable> entry : parameters.entrySet())
|
||||||
{
|
{
|
||||||
String paramName = entry.getKey();
|
String paramName = entry.getKey();
|
||||||
String path = AuditApplication.buildPath("params", paramName);
|
String path = AuditApplication.buildPath(action, "params", paramName);
|
||||||
adjustedValues.put(path, entry.getValue());
|
adjustedValues.put(path, entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,10 +203,9 @@ public class AuditComponentTest extends TestCase
|
|||||||
{
|
{
|
||||||
public Map<String, Serializable> execute() throws Throwable
|
public Map<String, Serializable> execute() throws Throwable
|
||||||
{
|
{
|
||||||
String actionPath = AuditApplication.buildPath("actions-test/actions", action);
|
String actionPath = AuditApplication.buildPath("actions-test/actions");
|
||||||
AuditSession session = auditComponent.startAuditSession(APPLICATION_ACTIONS_TEST, actionPath);
|
|
||||||
|
|
||||||
return auditComponent.audit(session, adjustedValues);
|
return auditComponent.audit(APPLICATION_ACTIONS_TEST, actionPath, adjustedValues);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return transactionService.getRetryingTransactionHelper().doInTransaction(auditCallback);
|
return transactionService.getRetryingTransactionHelper().doInTransaction(auditCallback);
|
||||||
@@ -279,7 +274,8 @@ public class AuditComponentTest extends TestCase
|
|||||||
Map<String, Serializable> result = auditTestAction("action-01", nodeRef, parameters);
|
Map<String, Serializable> result = auditTestAction("action-01", nodeRef, parameters);
|
||||||
|
|
||||||
Map<String, Serializable> expected = new HashMap<String, Serializable>();
|
Map<String, Serializable> expected = new HashMap<String, Serializable>();
|
||||||
expected.put("/actions-test/actions/action-01/context-node/noderef", nodeRef);
|
expected.put("/actions-test/actions/user", AuthenticationUtil.getFullyAuthenticatedUser());
|
||||||
|
expected.put("/actions-test/actions/context-node/noderef", nodeRef);
|
||||||
expected.put("/actions-test/actions/action-01/params/A/value", valueA);
|
expected.put("/actions-test/actions/action-01/params/A/value", valueA);
|
||||||
expected.put("/actions-test/actions/action-01/params/B/value", valueB);
|
expected.put("/actions-test/actions/action-01/params/B/value", valueB);
|
||||||
expected.put("/actions-test/actions/action-01/params/C/value", valueC);
|
expected.put("/actions-test/actions/action-01/params/C/value", valueC);
|
||||||
|
93
source/java/org/alfresco/repo/audit/AuditEntry.java
Normal file
93
source/java/org/alfresco/repo/audit/AuditEntry.java
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2009 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;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.util.ParameterCheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean to hold audit entry data. An audit entry represents a single audit call, but the
|
||||||
|
* data stored may be a large map.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public class AuditEntry
|
||||||
|
{
|
||||||
|
private final String user;
|
||||||
|
private final long time;
|
||||||
|
private final Long valuesId;
|
||||||
|
private final Map<String, Serializable> values;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Comment
|
||||||
|
*/
|
||||||
|
public AuditEntry(String user, long time, Long valuesId, Map<String, Serializable> values)
|
||||||
|
{
|
||||||
|
ParameterCheck.mandatoryString("user", user);
|
||||||
|
ParameterCheck.mandatory("time", time);
|
||||||
|
|
||||||
|
this.user = user;
|
||||||
|
this.time = time;
|
||||||
|
this.valuesId = valuesId;
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder(512);
|
||||||
|
sb.append("AuditEntry")
|
||||||
|
.append("[ user=").append(user)
|
||||||
|
.append(", time=").append(new Date(time))
|
||||||
|
.append(", valuesId=").append(valuesId)
|
||||||
|
.append(", values=").append(values)
|
||||||
|
.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUser()
|
||||||
|
{
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTime()
|
||||||
|
{
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getValuesId()
|
||||||
|
{
|
||||||
|
return valuesId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Serializable> getValues()
|
||||||
|
{
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
@@ -122,4 +122,16 @@ public class AuditServiceImpl implements AuditService
|
|||||||
tx.commit();
|
tx.commit();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* V3.2 from here on. Put all fixes to the older audit code before this point, please.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void auditQuery(AuditQueryCallback callback, String auditPath, String user, long from, long to, int limit)
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2005-2009 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;
|
|
||||||
|
|
||||||
import org.alfresco.repo.audit.model.AuditApplication;
|
|
||||||
import org.alfresco.util.ParameterCheck;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bean to hold session information for repeated use.
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
* @since 3.2
|
|
||||||
*/
|
|
||||||
public class AuditSession
|
|
||||||
{
|
|
||||||
private final AuditApplication application;
|
|
||||||
private final String rootPath;
|
|
||||||
private final Long sessionId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param application the audit application config being used
|
|
||||||
* @param rootPath the root path being used for the session
|
|
||||||
* @param sessionId the ID produced for the persisted session
|
|
||||||
*/
|
|
||||||
public AuditSession(AuditApplication application, String rootPath, Long sessionId)
|
|
||||||
{
|
|
||||||
ParameterCheck.mandatory("application", application);
|
|
||||||
ParameterCheck.mandatoryString("rootPath", rootPath);
|
|
||||||
ParameterCheck.mandatory("sessionId", sessionId);
|
|
||||||
|
|
||||||
this.application = application;
|
|
||||||
this.rootPath = rootPath;
|
|
||||||
this.sessionId = sessionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
return (application.hashCode() + rootPath.hashCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
|
||||||
if (this == obj)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (obj instanceof AuditSession)
|
|
||||||
{
|
|
||||||
AuditSession that = (AuditSession) obj;
|
|
||||||
return this.application.equals(that.application) &&
|
|
||||||
this.rootPath.equals(that.rootPath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder(512);
|
|
||||||
sb.append("AuditSession")
|
|
||||||
.append("[ application=").append(application)
|
|
||||||
.append(", rootPath=").append(rootPath)
|
|
||||||
.append(", sessionId=").append(sessionId)
|
|
||||||
.append("]");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuditApplication getApplication()
|
|
||||||
{
|
|
||||||
return application;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRootPath()
|
|
||||||
{
|
|
||||||
return rootPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getSessionId()
|
|
||||||
{
|
|
||||||
return sessionId;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -38,16 +38,6 @@ import java.io.Serializable;
|
|||||||
*/
|
*/
|
||||||
public interface DataGenerator
|
public interface DataGenerator
|
||||||
{
|
{
|
||||||
public static enum DataGeneratorScope
|
|
||||||
{
|
|
||||||
/** Data is generated for new audit sessions only */
|
|
||||||
SESSION,
|
|
||||||
/** Data is generated for individual audit calls only */
|
|
||||||
AUDIT,
|
|
||||||
/** Data is generated for new audit sessions and audit calls */
|
|
||||||
ALL
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the data generated by the instance.
|
* Get the data generated by the instance.
|
||||||
*
|
*
|
||||||
|
@@ -140,17 +140,6 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
|
|||||||
this.localSessionFactory = localSessionFactory;
|
this.localSessionFactory = localSessionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fallout implementation from new audit DAO
|
|
||||||
*
|
|
||||||
* @throws UnsupportedOperationException always
|
|
||||||
* @since 3.2
|
|
||||||
*/
|
|
||||||
public Long createAuditSession(Long modelId, String application)
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fallout implementation from new audit DAO
|
* Fallout implementation from new audit DAO
|
||||||
*
|
*
|
||||||
@@ -168,7 +157,18 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
|
|||||||
* @throws UnsupportedOperationException always
|
* @throws UnsupportedOperationException always
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public Long createAuditEntry(Long sessionId, long time, String username, Map<String, Serializable> values)
|
public Long getOrCreateAuditApplication(Long modelId, String applicationName)
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallout implementation from new audit DAO
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public Long createAuditEntry(Long applicationId, long time, String username, Map<String, Serializable> values)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
@@ -27,18 +27,15 @@ package org.alfresco.repo.audit.model;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.repo.audit.extractor.DataExtractor;
|
import org.alfresco.repo.audit.extractor.DataExtractor;
|
||||||
import org.alfresco.repo.audit.generator.DataGenerator;
|
import org.alfresco.repo.audit.generator.DataGenerator;
|
||||||
import org.alfresco.repo.audit.generator.DataGenerator.DataGeneratorScope;
|
|
||||||
import org.alfresco.repo.audit.model._3.Application;
|
import org.alfresco.repo.audit.model._3.Application;
|
||||||
import org.alfresco.repo.audit.model._3.AuditPath;
|
import org.alfresco.repo.audit.model._3.AuditPath;
|
||||||
import org.alfresco.repo.audit.model._3.GenerateValue;
|
import org.alfresco.repo.audit.model._3.GenerateValue;
|
||||||
import org.alfresco.repo.audit.model._3.RecordValue;
|
import org.alfresco.repo.audit.model._3.RecordValue;
|
||||||
import org.alfresco.repo.audit.model._3.ScopeAttribute;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
@@ -70,8 +67,6 @@ public class AuditApplication
|
|||||||
private Map<String, Map<String, DataExtractor>> dataExtractors = new HashMap<String, Map<String, DataExtractor>>(11);
|
private Map<String, Map<String, DataExtractor>> dataExtractors = new HashMap<String, Map<String, DataExtractor>>(11);
|
||||||
/** Derived expaned map for fast lookup */
|
/** Derived expaned map for fast lookup */
|
||||||
private Map<String, Map<String, DataGenerator>> dataGenerators = new HashMap<String, Map<String, DataGenerator>>(11);
|
private Map<String, Map<String, DataGenerator>> dataGenerators = new HashMap<String, Map<String, DataGenerator>>(11);
|
||||||
/** Derived expaned map for fast lookup */
|
|
||||||
private Map<String, DataGeneratorScope> dataGeneratorScopes = new HashMap<String, DataGeneratorScope>(11);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param application the application that will be wrapped
|
* @param application the application that will be wrapped
|
||||||
@@ -251,43 +246,29 @@ public class AuditApplication
|
|||||||
* Get all data generators applicable to a given path and scope.
|
* Get all data generators applicable to a given path and scope.
|
||||||
*
|
*
|
||||||
* @param path the audit path
|
* @param path the audit path
|
||||||
* @param scope the audit scope (e.g. SESSION or AUDIT)
|
|
||||||
* @return Returns all data generators mapped to their key-path
|
* @return Returns all data generators mapped to their key-path
|
||||||
*/
|
*/
|
||||||
public Map<String, DataGenerator> getDataGenerators(String path, DataGeneratorScope scope)
|
public Map<String, DataGenerator> getDataGenerators(String path)
|
||||||
{
|
{
|
||||||
Map<String, DataGenerator> generators = dataGenerators.get(path);
|
return getDataGenerators(Collections.singleton(path));
|
||||||
if (generators == null)
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all data generators applicable to a given path and scope.
|
||||||
|
*
|
||||||
|
* @param paths the audit paths
|
||||||
|
* @return Returns all data generators mapped to their key-path
|
||||||
|
*/
|
||||||
|
public Map<String, DataGenerator> getDataGenerators(Set<String> paths)
|
||||||
|
{
|
||||||
|
Map<String, DataGenerator> amalgamatedGenerators = new HashMap<String, DataGenerator>(13);
|
||||||
|
for (String path : paths)
|
||||||
{
|
{
|
||||||
// Don't give back a null
|
Map<String, DataGenerator> generators = dataGenerators.get(path);
|
||||||
generators = new HashMap<String, DataGenerator>(0);
|
if (generators != null)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Copy the map so that (a) we can modify it during iteration and (b) we return
|
|
||||||
// something that the client can't mess up.
|
|
||||||
generators = new HashMap<String, DataGenerator>(generators);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scope != DataGeneratorScope.ALL)
|
|
||||||
{
|
|
||||||
// Go through them and eliminate the ones in the wrong scope
|
|
||||||
Iterator<Map.Entry<String, DataGenerator>> iterator = generators.entrySet().iterator();
|
|
||||||
while (iterator.hasNext())
|
|
||||||
{
|
{
|
||||||
Map.Entry<String, DataGenerator> entry = iterator.next();
|
// Copy values to combined map
|
||||||
String generatorPath = entry.getKey();
|
amalgamatedGenerators.putAll(generators);
|
||||||
DataGeneratorScope generatorScope = dataGeneratorScopes.get(generatorPath);
|
|
||||||
if (generatorScope == DataGeneratorScope.ALL)
|
|
||||||
{
|
|
||||||
// This one always applies
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (generatorScope != scope)
|
|
||||||
{
|
|
||||||
// Wrong scope
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,11 +277,10 @@ public class AuditApplication
|
|||||||
{
|
{
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Looked up data generators: \n" +
|
"Looked up data generators: \n" +
|
||||||
" Path: " + path + "\n" +
|
" Paths: " + paths + "\n" +
|
||||||
" Scope: " + scope + "\n" +
|
" Found: " + amalgamatedGenerators);
|
||||||
" Found: " + generators);
|
|
||||||
}
|
}
|
||||||
return generators;
|
return amalgamatedGenerators;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -365,11 +345,11 @@ public class AuditApplication
|
|||||||
}
|
}
|
||||||
// All the extractors apply to the current path
|
// All the extractors apply to the current path
|
||||||
dataExtractors.put(currentPath, upperExtractorsByPath);
|
dataExtractors.put(currentPath, upperExtractorsByPath);
|
||||||
// // Data extractors only apply directly to data in which they appear.
|
// Data extractors only apply directly to data in which they appear.
|
||||||
// // TODO: Examine this assumption. If it is not true, i.e. data extractors apply to
|
// TODO: Examine this assumption. If it is not true, i.e. data extractors apply to
|
||||||
// // data anywhere down the hierarchy, then the followin line of code should be
|
// data anywhere down the hierarchy, then the followin line of code should be
|
||||||
// // removed and the use-cases tested appropriately.
|
// removed and the use-cases tested appropriately.
|
||||||
// upperExtractorsByPath.clear();
|
upperExtractorsByPath = new HashMap<String, DataExtractor>();
|
||||||
|
|
||||||
// Get the data generators declared for this key
|
// Get the data generators declared for this key
|
||||||
for (GenerateValue element : auditPath.getGenerateValue())
|
for (GenerateValue element : auditPath.getGenerateValue())
|
||||||
@@ -387,26 +367,6 @@ public class AuditApplication
|
|||||||
{
|
{
|
||||||
generateException(generatorPath, "No data generator exists for name: " + generatorName);
|
generateException(generatorPath, "No data generator exists for name: " + generatorName);
|
||||||
}
|
}
|
||||||
// Store the scope
|
|
||||||
ScopeAttribute scopeAttribute = element.getScope();
|
|
||||||
if (scopeAttribute == null)
|
|
||||||
{
|
|
||||||
generateException(generatorPath, "No scope defined for generator: " + generatorName);
|
|
||||||
}
|
|
||||||
String scopeStr = scopeAttribute.value();
|
|
||||||
if (scopeStr == null)
|
|
||||||
{
|
|
||||||
scopeStr = DataGeneratorScope.AUDIT.toString();
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DataGeneratorScope scope = DataGeneratorScope.valueOf(scopeStr);
|
|
||||||
dataGeneratorScopes.put(generatorPath, scope);
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
generateException(generatorPath, "Illegal generator scope value: " + scopeStr);
|
|
||||||
}
|
|
||||||
// All generators that occur earlier in the path will also be applicable here
|
// All generators that occur earlier in the path will also be applicable here
|
||||||
upperGeneratorsByPath.put(generatorPath, generator);
|
upperGeneratorsByPath.put(generatorPath, generator);
|
||||||
}
|
}
|
||||||
|
@@ -96,9 +96,9 @@ public class AuditModelRegistry
|
|||||||
*/
|
*/
|
||||||
private final Map<String, AuditApplication> auditApplicationsByName;
|
private final Map<String, AuditApplication> auditApplicationsByName;
|
||||||
/**
|
/**
|
||||||
* Used to lookup a reference to the persisted config binary for an application
|
* Used to lookup a reference to the application
|
||||||
*/
|
*/
|
||||||
private final Map<String, Long> auditModelIdsByApplicationsName;
|
private final Map<String, Long> auditApplicationIdsByApplicationsName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor
|
* Default constructor
|
||||||
@@ -114,7 +114,7 @@ public class AuditModelRegistry
|
|||||||
auditModelUrls = new HashSet<URL>(7);
|
auditModelUrls = new HashSet<URL>(7);
|
||||||
auditModels = new ArrayList<Audit>(7);
|
auditModels = new ArrayList<Audit>(7);
|
||||||
auditApplicationsByName = new HashMap<String, AuditApplication>(7);
|
auditApplicationsByName = new HashMap<String, AuditApplication>(7);
|
||||||
auditModelIdsByApplicationsName = new HashMap<String, Long>(7);
|
auditApplicationIdsByApplicationsName = new HashMap<String, Long>(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -209,7 +209,7 @@ public class AuditModelRegistry
|
|||||||
{
|
{
|
||||||
auditModels.clear();
|
auditModels.clear();
|
||||||
auditApplicationsByName.clear();
|
auditApplicationsByName.clear();
|
||||||
auditModelIdsByApplicationsName.clear();
|
auditApplicationIdsByApplicationsName.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,17 +271,17 @@ public class AuditModelRegistry
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the ID of the persisted audit model for the given application name
|
* Get the ID of the persisted audit application for the given application name
|
||||||
*
|
*
|
||||||
* @param applicationName the name of the audited application
|
* @param applicationName the name of the audited application
|
||||||
* @return the unique ID of the persisted model (<tt>null</tt> if not found)
|
* @return the unique ID of the persisted application (<tt>null</tt> if not found)
|
||||||
*/
|
*/
|
||||||
public Long getAuditModelId(String applicationName)
|
public Long getAuditApplicationId(String applicationName)
|
||||||
{
|
{
|
||||||
readLock.lock();
|
readLock.lock();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return auditModelIdsByApplicationsName.get(applicationName);
|
return auditApplicationIdsByApplicationsName.get(applicationName);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -514,9 +514,13 @@ public class AuditModelRegistry
|
|||||||
{
|
{
|
||||||
throw new AuditModelException("Audit application '" + name + "' has already been defined.");
|
throw new AuditModelException("Audit application '" + name + "' has already been defined.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the ID of the application
|
||||||
|
Long appId = auditDAO.getOrCreateAuditApplication(auditModelId, name);
|
||||||
|
|
||||||
AuditApplication wrapperApp = new AuditApplication(dataExtractorsByName, dataGeneratorsByName, application);
|
AuditApplication wrapperApp = new AuditApplication(dataExtractorsByName, dataGeneratorsByName, application);
|
||||||
auditApplicationsByName.put(name, wrapperApp);
|
auditApplicationsByName.put(name, wrapperApp);
|
||||||
auditModelIdsByApplicationsName.put(name, auditModelId);
|
auditApplicationIdsByApplicationsName.put(name, appId);
|
||||||
}
|
}
|
||||||
// Store the model itself
|
// Store the model itself
|
||||||
auditModels.add(audit);
|
auditModels.add(audit);
|
||||||
|
@@ -17,7 +17,6 @@ import javax.xml.bind.annotation.XmlType;
|
|||||||
* <complexContent>
|
* <complexContent>
|
||||||
* <extension base="{http://www.alfresco.org/repo/audit/model/3.2}KeyedAuditDefinition">
|
* <extension base="{http://www.alfresco.org/repo/audit/model/3.2}KeyedAuditDefinition">
|
||||||
* <attribute name="dataGenerator" use="required" type="{http://www.alfresco.org/repo/audit/model/3.2}NameAttribute" />
|
* <attribute name="dataGenerator" use="required" type="{http://www.alfresco.org/repo/audit/model/3.2}NameAttribute" />
|
||||||
* <attribute name="scope" use="required" type="{http://www.alfresco.org/repo/audit/model/3.2}ScopeAttribute" />
|
|
||||||
* </extension>
|
* </extension>
|
||||||
* </complexContent>
|
* </complexContent>
|
||||||
* </complexType>
|
* </complexType>
|
||||||
@@ -33,8 +32,6 @@ public class GenerateValue
|
|||||||
|
|
||||||
@XmlAttribute(required = true)
|
@XmlAttribute(required = true)
|
||||||
protected String dataGenerator;
|
protected String dataGenerator;
|
||||||
@XmlAttribute(required = true)
|
|
||||||
protected ScopeAttribute scope;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of the dataGenerator property.
|
* Gets the value of the dataGenerator property.
|
||||||
@@ -60,28 +57,4 @@ public class GenerateValue
|
|||||||
this.dataGenerator = value;
|
this.dataGenerator = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the scope property.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* possible object is
|
|
||||||
* {@link ScopeAttribute }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public ScopeAttribute getScope() {
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the scope property.
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
* allowed object is
|
|
||||||
* {@link ScopeAttribute }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void setScope(ScopeAttribute value) {
|
|
||||||
this.scope = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -34,11 +34,11 @@ public class ObjectFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of {@link KeyedAuditDefinition }
|
* Create an instance of {@link RecordValue }
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public KeyedAuditDefinition createKeyedAuditDefinition() {
|
public RecordValue createRecordValue() {
|
||||||
return new KeyedAuditDefinition();
|
return new RecordValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,14 +57,6 @@ public class ObjectFactory {
|
|||||||
return new Audit();
|
return new Audit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of {@link DataExtractors }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public DataExtractors createDataExtractors() {
|
|
||||||
return new DataExtractors();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of {@link AuditPath }
|
* Create an instance of {@link AuditPath }
|
||||||
*
|
*
|
||||||
@@ -90,11 +82,11 @@ public class ObjectFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of {@link RecordValue }
|
* Create an instance of {@link KeyedAuditDefinition }
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public RecordValue createRecordValue() {
|
public KeyedAuditDefinition createKeyedAuditDefinition() {
|
||||||
return new RecordValue();
|
return new KeyedAuditDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,6 +105,14 @@ public class ObjectFactory {
|
|||||||
return new GenerateValue();
|
return new GenerateValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of {@link DataExtractors }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public DataExtractors createDataExtractors() {
|
||||||
|
return new DataExtractors();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of {@link JAXBElement }{@code <}{@link Audit }{@code >}}
|
* Create an instance of {@link JAXBElement }{@code <}{@link Audit }{@code >}}
|
||||||
*
|
*
|
||||||
|
@@ -1,40 +0,0 @@
|
|||||||
|
|
||||||
package org.alfresco.repo.audit.model._3;
|
|
||||||
|
|
||||||
import javax.xml.bind.annotation.XmlEnum;
|
|
||||||
import javax.xml.bind.annotation.XmlType;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Java class for ScopeAttribute.
|
|
||||||
*
|
|
||||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
|
||||||
* <p>
|
|
||||||
* <pre>
|
|
||||||
* <simpleType name="ScopeAttribute">
|
|
||||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}string">
|
|
||||||
* <enumeration value="SESSION"/>
|
|
||||||
* <enumeration value="AUDIT"/>
|
|
||||||
* <enumeration value="ALL"/>
|
|
||||||
* </restriction>
|
|
||||||
* </simpleType>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@XmlType(name = "ScopeAttribute")
|
|
||||||
@XmlEnum
|
|
||||||
public enum ScopeAttribute {
|
|
||||||
|
|
||||||
SESSION,
|
|
||||||
AUDIT,
|
|
||||||
ALL;
|
|
||||||
|
|
||||||
public String value() {
|
|
||||||
return name();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ScopeAttribute fromValue(String v) {
|
|
||||||
return valueOf(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -56,7 +56,7 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractAuditDAOImpl implements AuditDAO
|
public abstract class AbstractAuditDAOImpl implements AuditDAO
|
||||||
{
|
{
|
||||||
private static final Log logger = LogFactory.getLog(AbstractAuditDAOImpl.class);
|
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||||
|
|
||||||
private HibernateAuditDAO oldDAO;
|
private HibernateAuditDAO oldDAO;
|
||||||
private ContentService contentService;
|
private ContentService contentService;
|
||||||
@@ -83,6 +83,11 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO
|
|||||||
this.propertyValueDAO = propertyValueDAO;
|
this.propertyValueDAO = propertyValueDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected PropertyValueDAO getPropertyValueDAO()
|
||||||
|
{
|
||||||
|
return this.propertyValueDAO;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for older audit DAO
|
* Support for older audit DAO
|
||||||
*/
|
*/
|
||||||
@@ -196,34 +201,42 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO
|
|||||||
protected abstract AuditModelEntity createAuditModel(Long contentDataId, long crc);
|
protected abstract AuditModelEntity createAuditModel(Long contentDataId, long crc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* alf_audit_session
|
* alf_audit_application
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public Long createAuditSession(Long modelId, String application)
|
public Long getOrCreateAuditApplication(Long modelId, String application)
|
||||||
{
|
{
|
||||||
// Persist the string
|
// Search for it
|
||||||
Long appNameId = propertyValueDAO.getOrCreatePropertyValue(application).getFirst();
|
AuditApplicationEntity entity = getAuditApplicationByModelIdAndName(modelId, application);
|
||||||
// Create the audit session
|
if (entity == null)
|
||||||
AuditSessionEntity entity = createAuditSession(appNameId, modelId);
|
|
||||||
// Done
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
{
|
||||||
logger.debug(
|
// Create it
|
||||||
"Created new audit session: \n" +
|
// Persist the string
|
||||||
" Model: " + modelId + "\n" +
|
Long appNameId = propertyValueDAO.getOrCreatePropertyValue(application).getFirst();
|
||||||
" App: " + application + "\n" +
|
// Create the audit session
|
||||||
" Result: " + entity);
|
entity = createAuditApplication(modelId, appNameId);
|
||||||
|
// Done
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug(
|
||||||
|
"Created new audit application: \n" +
|
||||||
|
" Model: " + modelId + "\n" +
|
||||||
|
" App: " + application + "\n" +
|
||||||
|
" Result: " + entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// Done
|
||||||
return entity.getId();
|
return entity.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract AuditSessionEntity createAuditSession(Long appNameId, Long modelId);
|
protected abstract AuditApplicationEntity getAuditApplicationByModelIdAndName(Long modelId, String appName);
|
||||||
|
protected abstract AuditApplicationEntity createAuditApplication(Long modelId, Long appNameId);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* alf_audit_entry
|
* alf_audit_entry
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public Long createAuditEntry(Long sessionId, long time, String username, Map<String, Serializable> values)
|
public Long createAuditEntry(Long applicationId, long time, String username, Map<String, Serializable> values)
|
||||||
{
|
{
|
||||||
final Long usernameId;
|
final Long usernameId;
|
||||||
if (username != null)
|
if (username != null)
|
||||||
@@ -242,20 +255,20 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the audit entry
|
// Create the audit entry
|
||||||
AuditEntryEntity entity = createAuditEntry(sessionId, time, usernameId, valuesId);
|
AuditEntryEntity entity = createAuditEntry(applicationId, time, usernameId, valuesId);
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Created new audit entry: \n" +
|
"Created new audit entry: \n" +
|
||||||
" Session: " + sessionId + "\n" +
|
" Application: " + applicationId + "\n" +
|
||||||
" Time: " + (new Date(time)) + "\n" +
|
" Time: " + (new Date(time)) + "\n" +
|
||||||
" User: " + username + "\n" +
|
" User: " + username + "\n" +
|
||||||
" Result: " + entity);
|
" Result: " + entity);
|
||||||
}
|
}
|
||||||
return entity.getId();
|
return entity.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract AuditEntryEntity createAuditEntry(Long sessionId, long time, Long usernameId, Long valuesId);
|
protected abstract AuditEntryEntity createAuditEntry(Long applicationId, long time, Long usernameId, Long valuesId);
|
||||||
}
|
}
|
||||||
|
@@ -25,18 +25,18 @@
|
|||||||
package org.alfresco.repo.domain.audit;
|
package org.alfresco.repo.domain.audit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity bean for <b>alf_audit_session</b> table.
|
* Entity bean for <b>alf_audit_application</b> table.
|
||||||
*
|
*
|
||||||
* @author Derek Hulley
|
* @author Derek Hulley
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public class AuditSessionEntity
|
public class AuditApplicationEntity
|
||||||
{
|
{
|
||||||
private Long id;
|
private Long id;
|
||||||
private Long applicationNameId;
|
|
||||||
private Long auditModelId;
|
private Long auditModelId;
|
||||||
|
private Long applicationNameId;
|
||||||
|
|
||||||
public AuditSessionEntity()
|
public AuditApplicationEntity()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,10 +44,10 @@ public class AuditSessionEntity
|
|||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder(512);
|
StringBuilder sb = new StringBuilder(512);
|
||||||
sb.append("AuditSessionEntity")
|
sb.append("AuditApplicationEntity")
|
||||||
.append("[ ID=").append(id)
|
.append("[ ID=").append(id)
|
||||||
.append(", applicationNameId=").append(applicationNameId)
|
|
||||||
.append(", auditModelId=").append(auditModelId)
|
.append(", auditModelId=").append(auditModelId)
|
||||||
|
.append(", applicationNameId=").append(applicationNameId)
|
||||||
.append("]");
|
.append("]");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
@@ -75,22 +75,22 @@ public interface AuditDAO
|
|||||||
Pair<Long, ContentData> getOrCreateAuditModel(URL url);
|
Pair<Long, ContentData> getOrCreateAuditModel(URL url);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new audit session entry - there is no session re-use.
|
* Creates a new audit application or finds an existing one
|
||||||
*
|
*
|
||||||
* @param modelId an existing audit model ID
|
* @param modelId the ID of the model configuration
|
||||||
* @param application the name of the application
|
* @param applicationName the name of the application
|
||||||
* @return Returns the unique session ID
|
* @return Returns the ID of the application entry
|
||||||
*/
|
*/
|
||||||
Long createAuditSession(Long modelId, String application);
|
Long getOrCreateAuditApplication(Long modelId, String applicationName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new audit entry with the given map of values.
|
* Create a new audit entry with the given map of values.
|
||||||
*
|
*
|
||||||
* @param sessionId an existing audit session ID
|
* @param applicationId an existing audit application ID
|
||||||
* @param time the time (ms since epoch) to log the entry against
|
* @param time the time (ms since epoch) to log the entry against
|
||||||
* @param username the authenticated user (<tt>null</tt> if not present)
|
* @param username the authenticated user (<tt>null</tt> if not present)
|
||||||
* @param values the values to record
|
* @param values the values to record
|
||||||
* @return Returns the unique entry ID
|
* @return Returns the unique entry ID
|
||||||
*/
|
*/
|
||||||
Long createAuditEntry(Long sessionId, long time, String username, Map<String, Serializable> values);
|
Long createAuditEntry(Long applicationId, long time, String username, Map<String, Serializable> values);
|
||||||
}
|
}
|
@@ -88,7 +88,7 @@ public class AuditDAOTest extends TestCase
|
|||||||
assertEquals(configPair, configPairCheck);
|
assertEquals(configPair, configPairCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuditSession() throws Exception
|
public void testAuditApplicatoin() throws Exception
|
||||||
{
|
{
|
||||||
final File file = AbstractContentTransformerTest.loadQuickTestFile("pdf");
|
final File file = AbstractContentTransformerTest.loadQuickTestFile("pdf");
|
||||||
assertNotNull(file);
|
assertNotNull(file);
|
||||||
@@ -104,22 +104,22 @@ public class AuditDAOTest extends TestCase
|
|||||||
|
|
||||||
final String appName = getName() + "." + System.currentTimeMillis();
|
final String appName = getName() + "." + System.currentTimeMillis();
|
||||||
final int count = 1000;
|
final int count = 1000;
|
||||||
RetryingTransactionCallback<Void> createSessionCallback = new RetryingTransactionCallback<Void>()
|
RetryingTransactionCallback<Void> createAppCallback = new RetryingTransactionCallback<Void>()
|
||||||
{
|
{
|
||||||
public Void execute() throws Throwable
|
public Void execute() throws Throwable
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
auditDAO.createAuditSession(modelId, appName);
|
auditDAO.getOrCreateAuditApplication(modelId, appName);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
long before = System.nanoTime();
|
long before = System.nanoTime();
|
||||||
txnHelper.doInTransaction(createSessionCallback);
|
txnHelper.doInTransaction(createAppCallback);
|
||||||
long after = System.nanoTime();
|
long after = System.nanoTime();
|
||||||
System.out.println(
|
System.out.println(
|
||||||
"Time for " + count + " session creations was " +
|
"Time for " + count + " application creations was " +
|
||||||
((double)(after - before)/(10E6)) + "ms");
|
((double)(after - before)/(10E6)) + "ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,15 +130,15 @@ public class AuditDAOTest extends TestCase
|
|||||||
final URL url = new URL("file:" + file.getAbsolutePath());
|
final URL url = new URL("file:" + file.getAbsolutePath());
|
||||||
final String appName = getName() + "." + System.currentTimeMillis();
|
final String appName = getName() + "." + System.currentTimeMillis();
|
||||||
|
|
||||||
RetryingTransactionCallback<Long> createSessionCallback = new RetryingTransactionCallback<Long>()
|
RetryingTransactionCallback<Long> createAppCallback = new RetryingTransactionCallback<Long>()
|
||||||
{
|
{
|
||||||
public Long execute() throws Throwable
|
public Long execute() throws Throwable
|
||||||
{
|
{
|
||||||
Long modelId = auditDAO.getOrCreateAuditModel(url).getFirst();
|
Long modelId = auditDAO.getOrCreateAuditModel(url).getFirst();
|
||||||
return auditDAO.createAuditSession(modelId, appName);
|
return auditDAO.getOrCreateAuditApplication(modelId, appName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
final Long sessionId = txnHelper.doInTransaction(createSessionCallback);
|
final Long sessionId = txnHelper.doInTransaction(createAppCallback);
|
||||||
|
|
||||||
final int count = 1000;
|
final int count = 1000;
|
||||||
final String username = "alexi";
|
final String username = "alexi";
|
||||||
|
@@ -35,7 +35,7 @@ import java.util.Date;
|
|||||||
public class AuditEntryEntity
|
public class AuditEntryEntity
|
||||||
{
|
{
|
||||||
private Long id;
|
private Long id;
|
||||||
private Long auditSessionId;
|
private Long auditApplicationId;
|
||||||
private Long auditUserId;
|
private Long auditUserId;
|
||||||
private long auditTime;
|
private long auditTime;
|
||||||
private Long auditValuesId;
|
private Long auditValuesId;
|
||||||
@@ -50,7 +50,7 @@ public class AuditEntryEntity
|
|||||||
StringBuilder sb = new StringBuilder(512);
|
StringBuilder sb = new StringBuilder(512);
|
||||||
sb.append("AuditEntryEntity")
|
sb.append("AuditEntryEntity")
|
||||||
.append("[ ID=").append(id)
|
.append("[ ID=").append(id)
|
||||||
.append(", auditSessionId=").append(auditSessionId)
|
.append(", auditApplicationId=").append(auditApplicationId)
|
||||||
.append(", auditTime").append(new Date(auditTime))
|
.append(", auditTime").append(new Date(auditTime))
|
||||||
.append(", auditValuesId=").append(auditValuesId)
|
.append(", auditValuesId=").append(auditValuesId)
|
||||||
.append("]");
|
.append("]");
|
||||||
@@ -67,14 +67,14 @@ public class AuditEntryEntity
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getAuditSessionId()
|
public Long getAuditApplicationId()
|
||||||
{
|
{
|
||||||
return auditSessionId;
|
return auditApplicationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAuditSessionId(Long auditSessionId)
|
public void setAuditApplicationId(Long auditSessionId)
|
||||||
{
|
{
|
||||||
this.auditSessionId = auditSessionId;
|
this.auditApplicationId = auditSessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getAuditUserId()
|
public Long getAuditUserId()
|
||||||
|
@@ -24,10 +24,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.domain.audit.ibatis;
|
package org.alfresco.repo.domain.audit.ibatis;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl;
|
import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl;
|
||||||
|
import org.alfresco.repo.domain.audit.AuditApplicationEntity;
|
||||||
import org.alfresco.repo.domain.audit.AuditEntryEntity;
|
import org.alfresco.repo.domain.audit.AuditEntryEntity;
|
||||||
import org.alfresco.repo.domain.audit.AuditModelEntity;
|
import org.alfresco.repo.domain.audit.AuditModelEntity;
|
||||||
import org.alfresco.repo.domain.audit.AuditSessionEntity;
|
import org.alfresco.util.Pair;
|
||||||
import org.springframework.orm.ibatis.SqlMapClientTemplate;
|
import org.springframework.orm.ibatis.SqlMapClientTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,7 +47,8 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
|
|||||||
private static final String SELECT_MODEL_BY_CRC = "select.AuditModelByCrc";
|
private static final String SELECT_MODEL_BY_CRC = "select.AuditModelByCrc";
|
||||||
private static final String INSERT_MODEL = "insert.AuditModel";
|
private static final String INSERT_MODEL = "insert.AuditModel";
|
||||||
|
|
||||||
private static final String INSERT_SESSION = "insert.AuditSession";
|
private static final String SELECT_APPLICATION_BY_MODEL_ID = "select.AuditApplicationByModelId";
|
||||||
|
private static final String INSERT_APPLICATION = "insert.AuditApplication";
|
||||||
|
|
||||||
private static final String INSERT_ENTRY = "insert.AuditEntry";
|
private static final String INSERT_ENTRY = "insert.AuditEntry";
|
||||||
|
|
||||||
@@ -75,22 +82,59 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
protected AuditSessionEntity createAuditSession(Long appNameId, Long modelId)
|
protected AuditApplicationEntity getAuditApplicationByModelIdAndName(Long modelId, String appName)
|
||||||
{
|
{
|
||||||
AuditSessionEntity entity = new AuditSessionEntity();
|
Map<String, Object> params = new HashMap<String, Object>(11);
|
||||||
entity.setApplicationNameId(appNameId);
|
params.put("id", modelId);
|
||||||
|
List<AuditApplicationEntity> results = (List<AuditApplicationEntity>) template.queryForList(
|
||||||
|
SELECT_APPLICATION_BY_MODEL_ID,
|
||||||
|
params);
|
||||||
|
// There could be multiple hits for the model ID. Go through them and find the correct app name.
|
||||||
|
AuditApplicationEntity result = null;
|
||||||
|
for (AuditApplicationEntity row : results)
|
||||||
|
{
|
||||||
|
Long appNameId = row.getApplicationNameId();
|
||||||
|
Pair<Long, Serializable> propPair = getPropertyValueDAO().getPropertyValueById(appNameId);
|
||||||
|
if (propPair == null)
|
||||||
|
{
|
||||||
|
// There is a FK to protect against this, but we'll just log it
|
||||||
|
logger.warn("An audit application references a non-existent app_name_id: " + appNameId);
|
||||||
|
}
|
||||||
|
// Check for exact match
|
||||||
|
Serializable propValue = propPair.getSecond();
|
||||||
|
if (propValue instanceof String && propValue.equals(appName))
|
||||||
|
{
|
||||||
|
// Got it
|
||||||
|
result = row;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Searched for audit application with model id " + modelId + " and found: " + result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AuditApplicationEntity createAuditApplication(Long modelId, Long appNameId)
|
||||||
|
{
|
||||||
|
AuditApplicationEntity entity = new AuditApplicationEntity();
|
||||||
entity.setAuditModelId(modelId);
|
entity.setAuditModelId(modelId);
|
||||||
Long id = (Long) template.insert(INSERT_SESSION, entity);
|
entity.setApplicationNameId(appNameId);
|
||||||
|
Long id = (Long) template.insert(INSERT_APPLICATION, entity);
|
||||||
entity.setId(id);
|
entity.setId(id);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AuditEntryEntity createAuditEntry(Long sessionId, long time, Long usernameId, Long valuesId)
|
protected AuditEntryEntity createAuditEntry(Long applicationId, long time, Long usernameId, Long valuesId)
|
||||||
{
|
{
|
||||||
AuditEntryEntity entity = new AuditEntryEntity();
|
AuditEntryEntity entity = new AuditEntryEntity();
|
||||||
entity.setAuditSessionId(sessionId);
|
entity.setAuditApplicationId(applicationId);
|
||||||
entity.setAuditTime(time);
|
entity.setAuditTime(time);
|
||||||
entity.setAuditUserId(usernameId);
|
entity.setAuditUserId(usernameId);
|
||||||
entity.setAuditValuesId(valuesId);
|
entity.setAuditValuesId(valuesId);
|
||||||
|
@@ -24,7 +24,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.service.cmr.audit;
|
package org.alfresco.service.cmr.audit;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.service.NotAuditable;
|
import org.alfresco.service.NotAuditable;
|
||||||
import org.alfresco.service.PublicService;
|
import org.alfresco.service.PublicService;
|
||||||
@@ -100,4 +102,62 @@ public interface AuditService
|
|||||||
*/
|
*/
|
||||||
@NotAuditable
|
@NotAuditable
|
||||||
public List<AuditInfo> getAuditTrail(NodeRef nodeRef);
|
public List<AuditInfo> getAuditTrail(NodeRef nodeRef);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* V3.2 from here on. Put all fixes to the older audit code before this point, please.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface that will be used to give query results to the calling code.
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public static interface AuditQueryCallback
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Check if summary or full data fetching is required. Depending on the return value,
|
||||||
|
* the underlying query may be completely different; it is not possible to change the
|
||||||
|
* return value and expect the callback to be used differently during row handling.
|
||||||
|
*
|
||||||
|
* @return Return <tt>true</tt> if summary data is required only i.e
|
||||||
|
* the full map of audit values for the entries will not be
|
||||||
|
* retrieved.
|
||||||
|
*/
|
||||||
|
boolean isSummaryOnly();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a summary row of audit entry data. The ID of the full values map is provided.
|
||||||
|
*
|
||||||
|
* @param applicationName the name of the application
|
||||||
|
* @param user the user that logged the entry
|
||||||
|
* @param time the time of the entry
|
||||||
|
* @param valuesId the ID of the values map as created
|
||||||
|
* @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop
|
||||||
|
*/
|
||||||
|
boolean handleAuditEntrySummary(String applicationName, String user, long time, Long valuesId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a full row of audit entry data.
|
||||||
|
*
|
||||||
|
* @param applicationName the name of the application
|
||||||
|
* @param user the user that logged the entry
|
||||||
|
* @param time the time of the entry
|
||||||
|
* @param values the values map as created
|
||||||
|
* @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop
|
||||||
|
*/
|
||||||
|
boolean handleAuditEntryFull(String applicationName, String user, long time, Map<String, Serializable> values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the audit entries that match the given criteria.
|
||||||
|
*
|
||||||
|
* @param callback the callback that will handle results
|
||||||
|
* @param auditPath if not <tt>null</tt>, at least one value in the entry must start with this path
|
||||||
|
* @param user if not <tt>null</tt>, the entry must be logged against this user
|
||||||
|
* @param from the start search time (use 0L) to cover all times
|
||||||
|
* @param to the end search time (use Long.MAX_VALUE) to cover all times
|
||||||
|
* @param limit the maximum number of results to retrieve
|
||||||
|
*/
|
||||||
|
void auditQuery(
|
||||||
|
AuditQueryCallback callback,
|
||||||
|
String auditPath, String user, long from, long to, int limit);
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
<Application name="Alfresco Test Bad 02" key="test-bad-02">
|
<Application name="Alfresco Test Bad 02" key="test-bad-02">
|
||||||
<AuditPath key="1.1">
|
<AuditPath key="1.1">
|
||||||
<AuditPath key="2.1">
|
<AuditPath key="2.1">
|
||||||
<GenerateValue key="value.1" dataGenerator="blah" scope="AUDIT"/>
|
<GenerateValue key="value.1" dataGenerator="blah"/>
|
||||||
</AuditPath>
|
</AuditPath>
|
||||||
</AuditPath>
|
</AuditPath>
|
||||||
</Application>
|
</Application>
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
<Application name="Alfresco Test Bad 05" key="test-bad-05">
|
<Application name="Alfresco Test Bad 05" key="test-bad-05">
|
||||||
<AuditPath key="1.1">
|
<AuditPath key="1.1">
|
||||||
<AuditPath key="2.1">
|
<AuditPath key="2.1">
|
||||||
<GenerateValue key="time" dataGenerator="systemTime" scope="SESSIOn"/>
|
<GenerateValue key="time" dataGenerator="systemTimeAAA"/>
|
||||||
</AuditPath>
|
</AuditPath>
|
||||||
</AuditPath>
|
</AuditPath>
|
||||||
</Application>
|
</Application>
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
<Application name="Alfresco Test Bad 06" key="test-bad-06">
|
<Application name="Alfresco Test Bad 06" key="test-bad-06">
|
||||||
<AuditPath key="1.1">
|
<AuditPath key="1.1">
|
||||||
<AuditPath key="2.1">
|
<AuditPath key="2.1">
|
||||||
<GenerateValue key="time" dataGenerator="systemTime" scope="SESSION"/>
|
<GenerateValue key="time" dataGenerator="systemTime"/>
|
||||||
</AuditPath>
|
</AuditPath>
|
||||||
</AuditPath>
|
</AuditPath>
|
||||||
</Application>
|
</Application>
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
</DataGenerators>
|
</DataGenerators>
|
||||||
|
|
||||||
<Application name="Alfresco Test" key="test">
|
<Application name="Alfresco Test" key="test">
|
||||||
<GenerateValue key="time" dataGenerator="systemTime" scope="SESSION"/>
|
<GenerateValue key="time" dataGenerator="systemTime"/>
|
||||||
<AuditPath key="1.1">
|
<AuditPath key="1.1">
|
||||||
<AuditPath key="2.1">
|
<AuditPath key="2.1">
|
||||||
<AuditPath key="3.1">
|
<AuditPath key="3.1">
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<AuditPath key="3.2">
|
<AuditPath key="3.2">
|
||||||
<AuditPath key="4.1">
|
<AuditPath key="4.1">
|
||||||
<RecordValue key="value.1" dataExtractor="simpleValue"/>
|
<RecordValue key="value.1" dataExtractor="simpleValue"/>
|
||||||
<GenerateValue key="time" dataGenerator="systemTime" scope="ALL"/>
|
<GenerateValue key="time" dataGenerator="systemTime"/>
|
||||||
</AuditPath>
|
</AuditPath>
|
||||||
<AuditPath key="4.2">
|
<AuditPath key="4.2">
|
||||||
<RecordValue key="value.1" dataExtractor="simpleValue"/>
|
<RecordValue key="value.1" dataExtractor="simpleValue"/>
|
||||||
@@ -67,12 +67,12 @@
|
|||||||
</Application>
|
</Application>
|
||||||
|
|
||||||
<Application name="Actions Test" key="actions-test">
|
<Application name="Actions Test" key="actions-test">
|
||||||
<GenerateValue key="time" dataGenerator="systemTime" scope="SESSION"/>
|
|
||||||
<AuditPath key="actions">
|
<AuditPath key="actions">
|
||||||
|
<GenerateValue key="user" dataGenerator="user"/>
|
||||||
|
<AuditPath key="context-node">
|
||||||
|
<RecordValue key="noderef" dataExtractor="simpleValue"/>
|
||||||
|
</AuditPath>
|
||||||
<AuditPath key="action-01">
|
<AuditPath key="action-01">
|
||||||
<AuditPath key="context-node">
|
|
||||||
<RecordValue key="noderef" dataExtractor="simpleValue"/>
|
|
||||||
</AuditPath>
|
|
||||||
<AuditPath key="params">
|
<AuditPath key="params">
|
||||||
<AuditPath key="A">
|
<AuditPath key="A">
|
||||||
<RecordValue key="value" dataExtractor="simpleValue"/>
|
<RecordValue key="value" dataExtractor="simpleValue"/>
|
||||||
|
Reference in New Issue
Block a user