mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Added source-target mappings for Audit data
- Audit entry creation API no longer requires an application name - Inbound data is remapped according to the mappings in the audit XML files git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16327 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element name="DataExtractors" type="a:DataExtractors" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="DataExtractors" type="a:DataExtractors" minOccurs="0" maxOccurs="1"/>
|
||||||
<xs:element name="DataGenerators" type="a:DataGenerators" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="DataGenerators" type="a:DataGenerators" minOccurs="0" maxOccurs="1"/>
|
||||||
|
<xs:element name="PathMappings" type="a:PathMappings" minOccurs="0" maxOccurs="1"/>
|
||||||
<xs:element name="Application" type="a:Application" minOccurs="0" maxOccurs="unbounded"/>
|
<xs:element name="Application" type="a:Application" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
@@ -50,11 +51,25 @@
|
|||||||
<xs:complexType name="Application">
|
<xs:complexType name="Application">
|
||||||
<xs:complexContent>
|
<xs:complexContent>
|
||||||
<xs:extension base="a:AuditPath">
|
<xs:extension base="a:AuditPath">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="PathMappings" type="a:PathMappings" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
<xs:attribute name="name" type="a:NameAttribute" use="required"/>
|
<xs:attribute name="name" type="a:NameAttribute" use="required"/>
|
||||||
</xs:extension>
|
</xs:extension>
|
||||||
</xs:complexContent>
|
</xs:complexContent>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="PathMappings">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="PathMap" type="a:PathMap" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:complexType name="PathMap">
|
||||||
|
<xs:attribute name="source" type="a:PathAttribute" use="required"/>
|
||||||
|
<xs:attribute name="target" type="a:PathAttribute" use="required"/>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
<xs:complexType name="AuditPath">
|
<xs:complexType name="AuditPath">
|
||||||
<xs:complexContent>
|
<xs:complexContent>
|
||||||
<xs:extension base="a:KeyedAuditDefinition">
|
<xs:extension base="a:KeyedAuditDefinition">
|
||||||
@@ -107,6 +122,14 @@
|
|||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="PathAttribute">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:minLength value="1"/>
|
||||||
|
<xs:maxLength value="128"/>
|
||||||
|
<xs:pattern value="(/([a-z]|[A-Z]|[0-9]|\-|\.)+)+"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
<xs:simpleType name="ClassAttribute">
|
<xs:simpleType name="ClassAttribute">
|
||||||
<xs:restriction base="xs:string">
|
<xs:restriction base="xs:string">
|
||||||
<xs:minLength value="1"/>
|
<xs:minLength value="1"/>
|
||||||
|
@@ -20,6 +20,10 @@
|
|||||||
<DataGenerator name="transactionId" class="org.alfresco.repo.audit.generator.TransactionIdDataGenerator"/>
|
<DataGenerator name="transactionId" class="org.alfresco.repo.audit.generator.TransactionIdDataGenerator"/>
|
||||||
</DataGenerators>
|
</DataGenerators>
|
||||||
|
|
||||||
|
<PathMappings>
|
||||||
|
<PathMap source="/repository" target="/repository"/>
|
||||||
|
</PathMappings>
|
||||||
|
|
||||||
<Application name="Alfresco Repository" key="repository">
|
<Application name="Alfresco Repository" key="repository">
|
||||||
<AuditPath key="services">
|
<AuditPath key="services">
|
||||||
<GenerateValue key="txn" dataGenerator="transactionId"/>
|
<GenerateValue key="txn" dataGenerator="transactionId"/>
|
||||||
|
@@ -35,6 +35,7 @@ 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;
|
||||||
import org.alfresco.util.ApplicationContextHelper;
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
|
import org.alfresco.util.PathMapper;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
@@ -51,6 +52,7 @@ import org.springframework.util.ResourceUtils;
|
|||||||
public class AuditBootstrapTest extends TestCase
|
public class AuditBootstrapTest extends TestCase
|
||||||
{
|
{
|
||||||
private static final String APPLICATION_TEST = "Alfresco Test";
|
private static final String APPLICATION_TEST = "Alfresco Test";
|
||||||
|
private static final String KEY_TEST = "test";
|
||||||
|
|
||||||
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||||
private static final Log logger = LogFactory.getLog(AuditBootstrapTest.class);
|
private static final Log logger = LogFactory.getLog(AuditBootstrapTest.class);
|
||||||
@@ -121,12 +123,33 @@ public class AuditBootstrapTest extends TestCase
|
|||||||
|
|
||||||
public void testGetApplicationId()
|
public void testGetApplicationId()
|
||||||
{
|
{
|
||||||
AuditApplication app = auditModelRegistry.getAuditApplication(APPLICATION_TEST);
|
AuditApplication app = auditModelRegistry.getAuditApplicationByName(APPLICATION_TEST);
|
||||||
assertNotNull(app);
|
assertNotNull(app);
|
||||||
Long appId = app.getApplicationId();
|
Long appId = app.getApplicationId();
|
||||||
assertNotNull("No audit application ID for " + APPLICATION_TEST, appId);
|
assertNotNull("No audit application ID for " + APPLICATION_TEST, appId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testGetApplicationByKey()
|
||||||
|
{
|
||||||
|
AuditApplication app = auditModelRegistry.getAuditApplicationByKey(KEY_TEST);
|
||||||
|
assertNotNull(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetPathMappings()
|
||||||
|
{
|
||||||
|
PathMapper pathMapper = auditModelRegistry.getAuditPathMapper();
|
||||||
|
assertNotNull(pathMapper);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pathMapper.addPathMap("x", "y");
|
||||||
|
fail("Should not be allowed to update the path mappings.");
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
// Expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void testBadPath(AuditApplication app, String path)
|
private void testBadPath(AuditApplication app, String path)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -142,7 +165,7 @@ public class AuditBootstrapTest extends TestCase
|
|||||||
|
|
||||||
public void testAuditApplication_Path()
|
public void testAuditApplication_Path()
|
||||||
{
|
{
|
||||||
AuditApplication app = auditModelRegistry.getAuditApplication(APPLICATION_TEST);
|
AuditApplication app = auditModelRegistry.getAuditApplicationByName(APPLICATION_TEST);
|
||||||
assertNotNull(app);
|
assertNotNull(app);
|
||||||
|
|
||||||
// Check that path checks are working
|
// Check that path checks are working
|
||||||
@@ -155,7 +178,7 @@ public class AuditBootstrapTest extends TestCase
|
|||||||
|
|
||||||
public void testAuditApplication_GetDataExtractors()
|
public void testAuditApplication_GetDataExtractors()
|
||||||
{
|
{
|
||||||
AuditApplication app = auditModelRegistry.getAuditApplication(APPLICATION_TEST);
|
AuditApplication app = auditModelRegistry.getAuditApplicationByName(APPLICATION_TEST);
|
||||||
assertNotNull(app);
|
assertNotNull(app);
|
||||||
|
|
||||||
Map<String, DataExtractor> extractors = app.getDataExtractors("/blah");
|
Map<String, DataExtractor> extractors = app.getDataExtractors("/blah");
|
||||||
@@ -173,7 +196,7 @@ public class AuditBootstrapTest extends TestCase
|
|||||||
|
|
||||||
public void testAuditApplication_GetDataGenerators()
|
public void testAuditApplication_GetDataGenerators()
|
||||||
{
|
{
|
||||||
AuditApplication app = auditModelRegistry.getAuditApplication(APPLICATION_TEST);
|
AuditApplication app = auditModelRegistry.getAuditApplicationByName(APPLICATION_TEST);
|
||||||
assertNotNull(app);
|
assertNotNull(app);
|
||||||
|
|
||||||
Map<String, DataGenerator> generators = app.getDataGenerators("/blah");
|
Map<String, DataGenerator> generators = app.getDataGenerators("/blah");
|
||||||
|
@@ -29,6 +29,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.repo.audit.model.AuditApplication;
|
import org.alfresco.repo.audit.model.AuditApplication;
|
||||||
|
import org.alfresco.repo.audit.model.AuditModelRegistry;
|
||||||
import org.alfresco.repo.audit.model._3.AuditPath;
|
import org.alfresco.repo.audit.model._3.AuditPath;
|
||||||
import org.alfresco.service.cmr.audit.AuditInfo;
|
import org.alfresco.service.cmr.audit.AuditInfo;
|
||||||
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
|
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
|
||||||
@@ -153,17 +154,22 @@ public interface AuditComponent
|
|||||||
void resetDisabledPaths(String applicationName);
|
void resetDisabledPaths(String applicationName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record a set of values against the given session. The map is a path - starting with '/'
|
* Create an audit entry for the given map of values. The map key 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 provided.
|
||||||
* {@link #startAuditSession(String, String) starting the session}. All resulting path values
|
*
|
||||||
* (session root path + map entry paths) must have data recorder entries and be enabled for data to be recorded.
|
* The root path and value keys are combined to produce a map of data keyed by full path. This
|
||||||
|
* fully-pathed map is then passed through the
|
||||||
|
* {@link AuditModelRegistry#getAuditPathMapper() audit path mapper}. The result may yield data
|
||||||
|
* destined for several different
|
||||||
|
* {@link AuditModelRegistry#getAuditApplicationByKey(String) audit applications}. depending on
|
||||||
|
* the data extraction and generation defined in the applications, values (or derived values) may
|
||||||
|
* be recorded against several audit entries (one per application represented).
|
||||||
* <p/>
|
* <p/>
|
||||||
* The return values reflect what was actually persisted and is controlled by the data extractors
|
* The return values reflect what was actually persisted and is controlled by the data extractors
|
||||||
* defined in the audit configuration.
|
* defined in the audit configuration.
|
||||||
* <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 applicationName the name of the application to log against
|
|
||||||
* @param rootPath a base path of {@link AuditPath} key entries concatenated with the path separator
|
* @param rootPath a base path of {@link AuditPath} key entries concatenated with the path separator
|
||||||
* '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR})
|
* '/' ({@link AuditApplication#AUDIT_PATH_SEPARATOR})
|
||||||
* @param values the values to audit mapped by {@link AuditPath} key relative to root path
|
* @param values the values to audit mapped by {@link AuditPath} key relative to root path
|
||||||
@@ -175,7 +181,7 @@ public interface AuditComponent
|
|||||||
*
|
*
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
Map<String, Serializable> audit(String applicationName, String rootPath, Map<String, Serializable> values);
|
Map<String, Serializable> recordAuditValues(String rootPath, Map<String, Serializable> values);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the audit entries that match the given criteria.
|
* Get the audit entries that match the given criteria.
|
||||||
|
@@ -64,6 +64,7 @@ import org.alfresco.service.cmr.search.SearchParameters;
|
|||||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
import org.alfresco.util.ParameterCheck;
|
import org.alfresco.util.ParameterCheck;
|
||||||
|
import org.alfresco.util.PathMapper;
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@@ -782,7 +783,7 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
{
|
{
|
||||||
this.propertyValueDAO = propertyValueDAO;
|
this.propertyValueDAO = propertyValueDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
@@ -790,13 +791,9 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
public void deleteAuditEntries(String applicationName, Long fromTime, Long toTime)
|
public void deleteAuditEntries(String applicationName, Long fromTime, Long toTime)
|
||||||
{
|
{
|
||||||
ParameterCheck.mandatory("applicationName", applicationName);
|
ParameterCheck.mandatory("applicationName", applicationName);
|
||||||
|
AlfrescoTransactionSupport.checkTransactionReadState(true);
|
||||||
|
|
||||||
if (AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_NONE)
|
AuditApplication application = auditModelRegistry.getAuditApplicationByName(applicationName);
|
||||||
{
|
|
||||||
throw new IllegalStateException("Auditing requires a read transaction.");
|
|
||||||
}
|
|
||||||
|
|
||||||
AuditApplication application = auditModelRegistry.getAuditApplication(applicationName);
|
|
||||||
if (application == null)
|
if (application == null)
|
||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
@@ -845,13 +842,9 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
{
|
{
|
||||||
ParameterCheck.mandatory("applicationName", applicationName);
|
ParameterCheck.mandatory("applicationName", applicationName);
|
||||||
ParameterCheck.mandatory("path", path);
|
ParameterCheck.mandatory("path", path);
|
||||||
|
AlfrescoTransactionSupport.checkTransactionReadState(false);
|
||||||
|
|
||||||
if (AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_NONE)
|
AuditApplication application = auditModelRegistry.getAuditApplicationByName(applicationName);
|
||||||
{
|
|
||||||
throw new IllegalStateException("Auditing requires a read transaction.");
|
|
||||||
}
|
|
||||||
|
|
||||||
AuditApplication application = auditModelRegistry.getAuditApplication(applicationName);
|
|
||||||
if (application == null)
|
if (application == null)
|
||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
@@ -895,13 +888,9 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
{
|
{
|
||||||
ParameterCheck.mandatory("applicationName", applicationName);
|
ParameterCheck.mandatory("applicationName", applicationName);
|
||||||
ParameterCheck.mandatory("path", path);
|
ParameterCheck.mandatory("path", path);
|
||||||
|
AlfrescoTransactionSupport.checkTransactionReadState(true);
|
||||||
|
|
||||||
if (AlfrescoTransactionSupport.getTransactionReadState() != TxnReadState.TXN_READ_WRITE)
|
AuditApplication application = auditModelRegistry.getAuditApplicationByName(applicationName);
|
||||||
{
|
|
||||||
throw new IllegalStateException("Auditing requires a read-write transaction.");
|
|
||||||
}
|
|
||||||
|
|
||||||
AuditApplication application = auditModelRegistry.getAuditApplication(applicationName);
|
|
||||||
if (application == null)
|
if (application == null)
|
||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
@@ -951,13 +940,9 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
{
|
{
|
||||||
ParameterCheck.mandatory("applicationName", applicationName);
|
ParameterCheck.mandatory("applicationName", applicationName);
|
||||||
ParameterCheck.mandatory("path", path);
|
ParameterCheck.mandatory("path", path);
|
||||||
|
AlfrescoTransactionSupport.checkTransactionReadState(true);
|
||||||
|
|
||||||
if (AlfrescoTransactionSupport.getTransactionReadState() != TxnReadState.TXN_READ_WRITE)
|
AuditApplication application = auditModelRegistry.getAuditApplicationByName(applicationName);
|
||||||
{
|
|
||||||
throw new IllegalStateException("Auditing requires a read-write transaction.");
|
|
||||||
}
|
|
||||||
|
|
||||||
AuditApplication application = auditModelRegistry.getAuditApplication(applicationName);
|
|
||||||
if (application == null)
|
if (application == null)
|
||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
@@ -1028,12 +1013,9 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
public void resetDisabledPaths(String applicationName)
|
public void resetDisabledPaths(String applicationName)
|
||||||
{
|
{
|
||||||
ParameterCheck.mandatory("applicationName", applicationName);
|
ParameterCheck.mandatory("applicationName", applicationName);
|
||||||
|
AlfrescoTransactionSupport.checkTransactionReadState(true);
|
||||||
|
|
||||||
if (AlfrescoTransactionSupport.getTransactionReadState() != TxnReadState.TXN_READ_WRITE)
|
AuditApplication application = auditModelRegistry.getAuditApplicationByName(applicationName);
|
||||||
{
|
|
||||||
throw new IllegalStateException("Auditing requires a read-write transaction.");
|
|
||||||
}
|
|
||||||
AuditApplication application = auditModelRegistry.getAuditApplication(applicationName);
|
|
||||||
if (application == null)
|
if (application == null)
|
||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
@@ -1055,56 +1037,16 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public Map<String, Serializable> audit(String applicationName, String rootPath, Map<String, Serializable> values)
|
public Map<String, Serializable> recordAuditValues(String rootPath, Map<String, Serializable> values)
|
||||||
{
|
{
|
||||||
ParameterCheck.mandatory("applicationName", applicationName);
|
|
||||||
ParameterCheck.mandatory("rootPath", rootPath);
|
ParameterCheck.mandatory("rootPath", rootPath);
|
||||||
|
AlfrescoTransactionSupport.checkTransactionReadState(true);
|
||||||
if (AlfrescoTransactionSupport.getTransactionReadState() != TxnReadState.TXN_READ_WRITE)
|
AuditApplication.checkPathFormat(rootPath);
|
||||||
|
|
||||||
|
if (values == null || values.isEmpty())
|
||||||
{
|
{
|
||||||
throw new IllegalStateException("Auditing requires a read-write transaction.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (values == null)
|
|
||||||
{
|
|
||||||
values = Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the application
|
|
||||||
AuditApplication application = auditModelRegistry.getAuditApplication(applicationName);
|
|
||||||
if (application == null)
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("No audit application named '" + applicationName + "' has been registered.");
|
|
||||||
}
|
|
||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
// Check the path against the application
|
|
||||||
application.checkPath(rootPath);
|
|
||||||
// Get the model ID for the application
|
|
||||||
Long applicationId = application.getApplicationId();
|
|
||||||
if (applicationId == null)
|
|
||||||
{
|
|
||||||
throw new AuditException("No persisted instance exists for audit application: " + applicationName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all disabled paths
|
|
||||||
Set<String> disabledPaths = getDisabledPaths(application);
|
|
||||||
// Check if the root path has been disabled
|
|
||||||
// This is a fast check and will usually be activated if there are any exclusions
|
|
||||||
for (String disabledPath : disabledPaths)
|
|
||||||
{
|
|
||||||
if (rootPath.startsWith(disabledPath))
|
|
||||||
{
|
|
||||||
logger.debug(
|
|
||||||
"Audit values root path has been excluded by disabled paths: \n" +
|
|
||||||
" Application: " + application + "\n" +
|
|
||||||
" Root Path: " + rootPath);
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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())
|
||||||
@@ -1114,8 +1056,82 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
pathedValues.put(path, entry.getValue());
|
pathedValues.put(path, entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Translate the values map
|
||||||
|
PathMapper pathMapper = auditModelRegistry.getAuditPathMapper();
|
||||||
|
Map<String, Serializable> mappedValues = pathMapper.convertMap(pathedValues);
|
||||||
|
|
||||||
|
// Group the values by root path
|
||||||
|
Map<String, Map<String, Serializable>> mappedValuesByRootKey = new HashMap<String, Map<String,Serializable>>();
|
||||||
|
for (Map.Entry<String, Serializable> entry : mappedValues.entrySet())
|
||||||
|
{
|
||||||
|
String path = entry.getKey();
|
||||||
|
String rootKey = AuditApplication.getRootKey(path);
|
||||||
|
Map<String, Serializable> rootKeyMappedValues = mappedValuesByRootKey.get(rootKey);
|
||||||
|
if (rootKeyMappedValues == null)
|
||||||
|
{
|
||||||
|
rootKeyMappedValues = new HashMap<String, Serializable>(7);
|
||||||
|
mappedValuesByRootKey.put(rootKey, rootKeyMappedValues);
|
||||||
|
}
|
||||||
|
rootKeyMappedValues.put(path, entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Serializable> allAuditedValues = new HashMap<String, Serializable>(values.size()*2+1);
|
||||||
|
// Now audit for each of the root keys
|
||||||
|
for (Map.Entry<String, Map<String, Serializable>> entry : mappedValuesByRootKey.entrySet())
|
||||||
|
{
|
||||||
|
String rootKey = entry.getKey();
|
||||||
|
Map<String, Serializable> rootKeyMappedValues = entry.getValue();
|
||||||
|
// Get the application
|
||||||
|
AuditApplication application = auditModelRegistry.getAuditApplicationByKey(rootKey);
|
||||||
|
if (application == null)
|
||||||
|
{
|
||||||
|
// There is no application that uses the root key
|
||||||
|
logger.debug(
|
||||||
|
"There is no application for root key: " + rootKey);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Get the disabled paths
|
||||||
|
Set<String> disabledPaths = getDisabledPaths(application);
|
||||||
|
// Do a quick elimination if the root path is disabled
|
||||||
|
if (disabledPaths.contains(AuditApplication.buildPath(rootKey)))
|
||||||
|
{
|
||||||
|
// The root key has been disabled for this application
|
||||||
|
logger.debug(
|
||||||
|
"Audit values root path has been excluded by disabled paths: \n" +
|
||||||
|
" Application: " + application + "\n" +
|
||||||
|
" Root Path: " + AuditApplication.buildPath(rootKey));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Do the audit
|
||||||
|
Map<String, Serializable> rootKeyAuditValues = audit(application, disabledPaths, rootKeyMappedValues);
|
||||||
|
allAuditedValues.putAll(rootKeyAuditValues);
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
return allAuditedValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit values for a given application. No path checking is done.
|
||||||
|
*
|
||||||
|
* @param application the audit application to audit to
|
||||||
|
* @param disabledPaths the application's disabled paths
|
||||||
|
* @param values the values to store keyed by <b>full paths</b>.
|
||||||
|
* @return Returns all values as audited
|
||||||
|
*/
|
||||||
|
private Map<String, Serializable> audit(
|
||||||
|
AuditApplication application,
|
||||||
|
Set<String> disabledPaths,
|
||||||
|
Map<String, Serializable> values)
|
||||||
|
{
|
||||||
|
// Get the model ID for the application
|
||||||
|
Long applicationId = application.getApplicationId();
|
||||||
|
if (applicationId == null)
|
||||||
|
{
|
||||||
|
throw new AuditException("No persisted instance exists for audit application: " + application);
|
||||||
|
}
|
||||||
|
|
||||||
// Eliminate any paths that have been disabled
|
// Eliminate any paths that have been disabled
|
||||||
Iterator<String> pathedValuesKeyIterator = pathedValues.keySet().iterator();
|
Iterator<String> pathedValuesKeyIterator = values.keySet().iterator();
|
||||||
while(pathedValuesKeyIterator.hasNext())
|
while(pathedValuesKeyIterator.hasNext())
|
||||||
{
|
{
|
||||||
String pathedValueKey = pathedValuesKeyIterator.next();
|
String pathedValueKey = pathedValuesKeyIterator.next();
|
||||||
@@ -1129,25 +1145,24 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if there is anything left
|
// Check if there is anything left
|
||||||
if (pathedValues.size() == 0)
|
if (values.size() == 0)
|
||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Audit values have all been excluded by disabled paths: \n" +
|
"Audit values have all been excluded by disabled paths: \n" +
|
||||||
" Application: " + application + "\n" +
|
" Application: " + application + "\n" +
|
||||||
" Root Path: " + rootPath + "\n" +
|
|
||||||
" Values: " + values);
|
" Values: " + values);
|
||||||
}
|
}
|
||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate data
|
// Generate data
|
||||||
Map<String, DataGenerator> generators = application.getDataGenerators(pathedValues.keySet());
|
Map<String, DataGenerator> generators = application.getDataGenerators(values.keySet());
|
||||||
Map<String, Serializable> auditData = generateData(generators);
|
Map<String, Serializable> auditData = generateData(generators);
|
||||||
|
|
||||||
// Now extract values
|
// Now extract values
|
||||||
Map<String, Serializable> extractedData = extractData(application, pathedValues);
|
Map<String, Serializable> extractedData = extractData(application, values);
|
||||||
|
|
||||||
// Combine extracted and generated values (extracted data takes precedence)
|
// Combine extracted and generated values (extracted data takes precedence)
|
||||||
auditData.putAll(extractedData);
|
auditData.putAll(extractedData);
|
||||||
@@ -1168,9 +1183,9 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
{
|
{
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"New audit entry: \n" +
|
"New audit entry: \n" +
|
||||||
" Applicatoin ID: " + applicationId + "\n" +
|
" Application ID: " + applicationId + "\n" +
|
||||||
" Entry ID: " + entryId + "\n" +
|
" Entry ID: " + entryId + "\n" +
|
||||||
" Path Values: " + pathedValues + "\n" +
|
" Values: " + values + "\n" +
|
||||||
" Audit Data: " + auditData);
|
" Audit Data: " + auditData);
|
||||||
}
|
}
|
||||||
return auditData;
|
return auditData;
|
||||||
|
@@ -26,6 +26,7 @@ package org.alfresco.repo.audit;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -133,7 +134,7 @@ public class AuditComponentTest extends TestCase
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auditComponent.audit(APPLICATION_TEST, "/test", null);
|
auditComponent.recordAuditValues("/test", Collections.<String, Serializable>emptyMap());
|
||||||
fail("Should fail due to lack of a transaction.");
|
fail("Should fail due to lack of a transaction.");
|
||||||
}
|
}
|
||||||
catch (IllegalStateException e)
|
catch (IllegalStateException e)
|
||||||
@@ -146,7 +147,7 @@ public class AuditComponentTest extends TestCase
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auditComponent.audit(APPLICATION_TEST, "test", null);
|
auditComponent.recordAuditValues("test", null);
|
||||||
fail("Failed to detect illegal path");
|
fail("Failed to detect illegal path");
|
||||||
}
|
}
|
||||||
catch (AuditModelException e)
|
catch (AuditModelException e)
|
||||||
@@ -155,14 +156,14 @@ public class AuditComponentTest extends TestCase
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auditComponent.audit(APPLICATION_TEST, "/test/", null);
|
auditComponent.recordAuditValues("/test/", null);
|
||||||
fail("Failed to detect illegal path");
|
fail("Failed to detect illegal path");
|
||||||
}
|
}
|
||||||
catch (AuditModelException e)
|
catch (AuditModelException e)
|
||||||
{
|
{
|
||||||
// Expected
|
// Expected
|
||||||
}
|
}
|
||||||
Map<String, Serializable> auditedValues = auditComponent.audit("Bogus App", "/test", null);
|
Map<String, Serializable> auditedValues = auditComponent.recordAuditValues("/bogus", null);
|
||||||
assertNotNull(auditedValues);
|
assertNotNull(auditedValues);
|
||||||
assertTrue("Invalid application should not audit anything", auditedValues.isEmpty());
|
assertTrue("Invalid application should not audit anything", auditedValues.isEmpty());
|
||||||
|
|
||||||
@@ -182,11 +183,11 @@ public class AuditComponentTest extends TestCase
|
|||||||
public Void execute() throws Throwable
|
public Void execute() throws Throwable
|
||||||
{
|
{
|
||||||
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("/2.1/3.1/4.1", new Long(41));
|
||||||
values.put("/test/1.1/2.1/3.1/4.2", "42");
|
values.put("/2.1/3.1/4.2", "42");
|
||||||
values.put("/test/1.1/2.1/3.1/4.2", new Date());
|
values.put("/2.1/3.1/4.2", new Date());
|
||||||
|
|
||||||
auditComponent.audit(APPLICATION_TEST, "/test/1.1", values);
|
auditComponent.recordAuditValues("/test/1.1", values);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -224,7 +225,7 @@ public class AuditComponentTest extends TestCase
|
|||||||
{
|
{
|
||||||
String actionPath = AuditApplication.buildPath("actions-test/actions");
|
String actionPath = AuditApplication.buildPath("actions-test/actions");
|
||||||
|
|
||||||
return auditComponent.audit(APPLICATION_ACTIONS_TEST, actionPath, adjustedValues);
|
return auditComponent.recordAuditValues(actionPath, adjustedValues);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return transactionService.getRetryingTransactionHelper().doInTransaction(auditCallback);
|
return transactionService.getRetryingTransactionHelper().doInTransaction(auditCallback);
|
||||||
@@ -235,47 +236,17 @@ public class AuditComponentTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
private void checkAuditMaps(Map<String, Serializable> result, Map<String, Serializable> expected)
|
private void checkAuditMaps(Map<String, Serializable> result, Map<String, Serializable> expected)
|
||||||
{
|
{
|
||||||
Map<String, Serializable> copyResult = new HashMap<String, Serializable>(result);
|
String failure = EqualsHelper.getMapDifferenceReport(result, expected);
|
||||||
|
if (failure != null)
|
||||||
boolean failure = false;
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder(1024);
|
|
||||||
sb.append("\nValues that don't match the expected values: ");
|
|
||||||
for (Map.Entry<String, Serializable> entry : expected.entrySet())
|
|
||||||
{
|
{
|
||||||
String key = entry.getKey();
|
fail(failure);
|
||||||
Serializable expectedValue = entry.getValue();
|
|
||||||
Serializable resultValue = result.get(key);
|
|
||||||
if (!EqualsHelper.nullSafeEquals(resultValue, expectedValue))
|
|
||||||
{
|
|
||||||
sb.append("\n")
|
|
||||||
.append(" Key: ").append(key).append("\n")
|
|
||||||
.append(" Result: ").append(resultValue).append("\n")
|
|
||||||
.append(" Expected: ").append(expectedValue);
|
|
||||||
failure = true;
|
|
||||||
}
|
|
||||||
copyResult.remove(key);
|
|
||||||
}
|
|
||||||
sb.append("\nValues that are present but should not be: ");
|
|
||||||
for (Map.Entry<String, Serializable> entry : copyResult.entrySet())
|
|
||||||
{
|
|
||||||
String key = entry.getKey();
|
|
||||||
Serializable resultValue = entry.getValue();
|
|
||||||
sb.append("\n")
|
|
||||||
.append(" Key: ").append(key).append("\n")
|
|
||||||
.append(" Result: ").append(resultValue);
|
|
||||||
failure = true;
|
|
||||||
}
|
|
||||||
if (failure)
|
|
||||||
{
|
|
||||||
fail(sb.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test auditing of something resembling real-world data
|
* Test auditing of something resembling real-world data
|
||||||
*/
|
*/
|
||||||
public void testAudit_Action01() throws Exception
|
private void auditAction01(String actionName) throws Exception
|
||||||
{
|
{
|
||||||
Serializable valueA = new Date();
|
Serializable valueA = new Date();
|
||||||
Serializable valueB = "BBB-value-here";
|
Serializable valueB = "BBB-value-here";
|
||||||
@@ -290,7 +261,7 @@ public class AuditComponentTest extends TestCase
|
|||||||
parameters.put("b", valueB);
|
parameters.put("b", valueB);
|
||||||
parameters.put("c", valueC);
|
parameters.put("c", valueC);
|
||||||
|
|
||||||
Map<String, Serializable> result = auditTestAction("action-01", nodeRef, parameters);
|
Map<String, Serializable> result = auditTestAction(actionName, nodeRef, parameters);
|
||||||
|
|
||||||
Map<String, Serializable> expected = new HashMap<String, Serializable>();
|
Map<String, Serializable> expected = new HashMap<String, Serializable>();
|
||||||
expected.put("/actions-test/actions/user", AuthenticationUtil.getFullyAuthenticatedUser());
|
expected.put("/actions-test/actions/user", AuthenticationUtil.getFullyAuthenticatedUser());
|
||||||
@@ -303,6 +274,22 @@ public class AuditComponentTest extends TestCase
|
|||||||
checkAuditMaps(result, expected);
|
checkAuditMaps(result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test auditing of something resembling real-world data
|
||||||
|
*/
|
||||||
|
public void testAudit_Action01() throws Exception
|
||||||
|
{
|
||||||
|
auditAction01("action-01");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test auditing of something resembling real-world data
|
||||||
|
*/
|
||||||
|
public void testAudit_Action01Mapped() throws Exception
|
||||||
|
{
|
||||||
|
auditAction01("action-01-mapped");
|
||||||
|
}
|
||||||
|
|
||||||
public void testQuery_Action01() throws Exception
|
public void testQuery_Action01() throws Exception
|
||||||
{
|
{
|
||||||
final Long beforeTime = new Long(System.currentTimeMillis());
|
final Long beforeTime = new Long(System.currentTimeMillis());
|
||||||
|
@@ -174,6 +174,7 @@ public class AuditApplication
|
|||||||
*/
|
*/
|
||||||
public void checkPath(String path)
|
public void checkPath(String path)
|
||||||
{
|
{
|
||||||
|
checkPathFormat(path);
|
||||||
if (path == null || path.length() == 0)
|
if (path == null || path.length() == 0)
|
||||||
{
|
{
|
||||||
generateException(path, "Empty or null audit path");
|
generateException(path, "Empty or null audit path");
|
||||||
@@ -192,6 +193,26 @@ public class AuditApplication
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to check that a path is correct for this application instance
|
||||||
|
*
|
||||||
|
* @param path the path in format <b>/app-key/x/y/z</b>
|
||||||
|
* @throws AuditModelException if the path is invalid
|
||||||
|
*
|
||||||
|
* @see #AUDIT_PATH_REGEX
|
||||||
|
*/
|
||||||
|
public static void checkPathFormat(String path)
|
||||||
|
{
|
||||||
|
if (path == null || path.length() == 0)
|
||||||
|
{
|
||||||
|
throw new AuditModelException("Empty or null audit path");
|
||||||
|
}
|
||||||
|
else if (!path.matches(AUDIT_PATH_REGEX))
|
||||||
|
{
|
||||||
|
throw new AuditModelException("An audit must match regular expression: " + AUDIT_PATH_REGEX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile a path or part of a path into a single string which always starts with the
|
* Compile a path or part of a path into a single string which always starts with the
|
||||||
* {@link #AUDIT_PATH_SEPARATOR}. This can be a relative path so need not always start with
|
* {@link #AUDIT_PATH_SEPARATOR}. This can be a relative path so need not always start with
|
||||||
@@ -237,6 +258,33 @@ public class AuditApplication
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path the audit path for form <b>/abc/def</b>
|
||||||
|
* @return the root key of form <b>abc</b>
|
||||||
|
*
|
||||||
|
* @see #AUDIT_ROOT_KEY_REGEX
|
||||||
|
*/
|
||||||
|
public static String getRootKey(String path)
|
||||||
|
{
|
||||||
|
if (!path.startsWith(AUDIT_PATH_SEPARATOR))
|
||||||
|
{
|
||||||
|
throw new AuditModelException(
|
||||||
|
"The path must start with the path separator '" + AUDIT_PATH_SEPARATOR + "'");
|
||||||
|
}
|
||||||
|
String rootPath;
|
||||||
|
int index = path.indexOf(AUDIT_PATH_SEPARATOR, 1);
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
rootPath = path.substring(1, index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rootPath = path.substring(1);
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
return rootPath;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all data extractors applicable to a given path and scope.
|
* Get all data extractors applicable to a given path and scope.
|
||||||
*
|
*
|
||||||
|
@@ -54,11 +54,14 @@ import org.alfresco.repo.audit.model._3.Audit;
|
|||||||
import org.alfresco.repo.audit.model._3.DataExtractors;
|
import org.alfresco.repo.audit.model._3.DataExtractors;
|
||||||
import org.alfresco.repo.audit.model._3.DataGenerators;
|
import org.alfresco.repo.audit.model._3.DataGenerators;
|
||||||
import org.alfresco.repo.audit.model._3.ObjectFactory;
|
import org.alfresco.repo.audit.model._3.ObjectFactory;
|
||||||
|
import org.alfresco.repo.audit.model._3.PathMap;
|
||||||
|
import org.alfresco.repo.audit.model._3.PathMappings;
|
||||||
import org.alfresco.repo.domain.audit.AuditDAO;
|
import org.alfresco.repo.domain.audit.AuditDAO;
|
||||||
import org.alfresco.repo.domain.audit.AuditDAO.AuditApplicationInfo;
|
import org.alfresco.repo.domain.audit.AuditDAO.AuditApplicationInfo;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.PathMapper;
|
||||||
import org.alfresco.util.PropertyCheck;
|
import org.alfresco.util.PropertyCheck;
|
||||||
import org.alfresco.util.registry.NamedObjectRegistry;
|
import org.alfresco.util.registry.NamedObjectRegistry;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
@@ -92,6 +95,14 @@ public class AuditModelRegistry
|
|||||||
|
|
||||||
private final Set<URL> auditModelUrls;
|
private final Set<URL> auditModelUrls;
|
||||||
private final List<Audit> auditModels;
|
private final List<Audit> auditModels;
|
||||||
|
/**
|
||||||
|
* Used to lookup path translations
|
||||||
|
*/
|
||||||
|
private PathMapper auditPathMapper;
|
||||||
|
/**
|
||||||
|
* Used to lookup the audit application java hierarchy
|
||||||
|
*/
|
||||||
|
private final Map<String, AuditApplication> auditApplicationsByKey;
|
||||||
/**
|
/**
|
||||||
* Used to lookup the audit application java hierarchy
|
* Used to lookup the audit application java hierarchy
|
||||||
*/
|
*/
|
||||||
@@ -110,6 +121,8 @@ public class AuditModelRegistry
|
|||||||
|
|
||||||
auditModelUrls = new HashSet<URL>(7);
|
auditModelUrls = new HashSet<URL>(7);
|
||||||
auditModels = new ArrayList<Audit>(7);
|
auditModels = new ArrayList<Audit>(7);
|
||||||
|
auditPathMapper = new PathMapper();
|
||||||
|
auditApplicationsByKey = new HashMap<String, AuditApplication>(7);
|
||||||
auditApplicationsByName = new HashMap<String, AuditApplication>(7);
|
auditApplicationsByName = new HashMap<String, AuditApplication>(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +217,7 @@ public class AuditModelRegistry
|
|||||||
private void clearCaches()
|
private void clearCaches()
|
||||||
{
|
{
|
||||||
auditModels.clear();
|
auditModels.clear();
|
||||||
|
auditApplicationsByKey.clear();
|
||||||
auditApplicationsByName.clear();
|
auditApplicationsByName.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,11 +241,11 @@ public class AuditModelRegistry
|
|||||||
Set<URL> auditModelUrlsInner = new HashSet<URL>(auditModelUrls);
|
Set<URL> auditModelUrlsInner = new HashSet<URL>(auditModelUrls);
|
||||||
for (URL auditModelUrl : auditModelUrlsInner)
|
for (URL auditModelUrl : auditModelUrlsInner)
|
||||||
{
|
{
|
||||||
Audit audit = AuditModelRegistry.unmarshallModel(auditModelUrl);
|
|
||||||
// That worked, so now get an input stream and write the model
|
|
||||||
Long auditModelId = auditDAO.getOrCreateAuditModel(auditModelUrl).getFirst();
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Audit audit = AuditModelRegistry.unmarshallModel(auditModelUrl);
|
||||||
|
// That worked, so now get an input stream and write the model
|
||||||
|
Long auditModelId = auditDAO.getOrCreateAuditModel(auditModelUrl).getFirst();
|
||||||
// Now cache it (eagerly)
|
// Now cache it (eagerly)
|
||||||
cacheAuditElements(auditModelId, audit);
|
cacheAuditElements(auditModelId, audit);
|
||||||
}
|
}
|
||||||
@@ -258,7 +272,9 @@ public class AuditModelRegistry
|
|||||||
clearCaches();
|
clearCaches();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
auditPathMapper = new PathMapper();
|
||||||
transactionService.getRetryingTransactionHelper().doInTransaction(loadModelsCallback, false, true);
|
transactionService.getRetryingTransactionHelper().doInTransaction(loadModelsCallback, false, true);
|
||||||
|
auditPathMapper.lock();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -266,13 +282,32 @@ public class AuditModelRegistry
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the application model for the given root key (as defined on the application)
|
||||||
|
*
|
||||||
|
* @param key the key defined on the application
|
||||||
|
* @return the java model (<tt>null</tt> if not found)
|
||||||
|
*/
|
||||||
|
public AuditApplication getAuditApplicationByKey(String key)
|
||||||
|
{
|
||||||
|
readLock.lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return auditApplicationsByKey.get(key);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the application model for the given application name
|
* Get the application model for the given application name
|
||||||
*
|
*
|
||||||
* @param applicationName the name of the audited application
|
* @param applicationName the name of the audited application
|
||||||
* @return the java model (<tt>null</tt> if not found)
|
* @return the java model (<tt>null</tt> if not found)
|
||||||
*/
|
*/
|
||||||
public AuditApplication getAuditApplication(String applicationName)
|
public AuditApplication getAuditApplicationByName(String applicationName)
|
||||||
{
|
{
|
||||||
readLock.lock();
|
readLock.lock();
|
||||||
try
|
try
|
||||||
@@ -285,6 +320,15 @@ public class AuditModelRegistry
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public PathMapper getAuditPathMapper()
|
||||||
|
{
|
||||||
|
return auditPathMapper;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unmarshalls the Audit model from the URL.
|
* Unmarshalls the Audit model from the URL.
|
||||||
*
|
*
|
||||||
@@ -331,7 +375,7 @@ public class AuditModelRegistry
|
|||||||
" Location: Line " + locator.getLineNumber() + " column " + locator.getColumnNumber() + "\n" +
|
" Location: Line " + locator.getLineNumber() + " column " + locator.getColumnNumber() + "\n" +
|
||||||
" Error: " + ve.getMessage());
|
" Error: " + ve.getMessage());
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -486,10 +530,18 @@ public class AuditModelRegistry
|
|||||||
List<Application> applications = audit.getApplication();
|
List<Application> applications = audit.getApplication();
|
||||||
for (Application application : applications)
|
for (Application application : applications)
|
||||||
{
|
{
|
||||||
|
String key = application.getKey();
|
||||||
|
if (auditApplicationsByKey.containsKey(key))
|
||||||
|
{
|
||||||
|
throw new AuditModelException(
|
||||||
|
"Audit application key '" + key + "' is used by: " + auditApplicationsByKey.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
String name = application.getName();
|
String name = application.getName();
|
||||||
if (auditApplicationsByName.containsKey(name))
|
if (auditApplicationsByName.containsKey(name))
|
||||||
{
|
{
|
||||||
throw new AuditModelException("Audit application '" + name + "' has already been defined.");
|
throw new AuditModelException(
|
||||||
|
"Audit application '" + name + "' is used by: " + auditApplicationsByName.get(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the ID of the application
|
// Get the ID of the application
|
||||||
@@ -511,8 +563,29 @@ public class AuditModelRegistry
|
|||||||
appInfo.getId(),
|
appInfo.getId(),
|
||||||
appInfo.getDisabledPathsId());
|
appInfo.getDisabledPathsId());
|
||||||
auditApplicationsByName.put(name, wrapperApp);
|
auditApplicationsByName.put(name, wrapperApp);
|
||||||
|
auditApplicationsByKey.put(key, wrapperApp);
|
||||||
}
|
}
|
||||||
|
// Pull out all the audit path maps
|
||||||
|
buildAuditPathMap(audit);
|
||||||
// Store the model itself
|
// Store the model itself
|
||||||
auditModels.add(audit);
|
auditModels.add(audit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the reverse lookup maps for quick conversion of data to target maps
|
||||||
|
*/
|
||||||
|
private void buildAuditPathMap(Audit audit)
|
||||||
|
{
|
||||||
|
PathMappings pathMappings = audit.getPathMappings();
|
||||||
|
if (pathMappings == null)
|
||||||
|
{
|
||||||
|
pathMappings = objectFactory.createPathMappings();
|
||||||
|
}
|
||||||
|
for (PathMap pathMap : pathMappings.getPathMap())
|
||||||
|
{
|
||||||
|
String sourcePath = pathMap.getSource();
|
||||||
|
String targetPath = pathMap.getTarget();
|
||||||
|
auditPathMapper.addPathMap(sourcePath, targetPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,12 @@
|
|||||||
|
|
||||||
package org.alfresco.repo.audit.model._3;
|
package org.alfresco.repo.audit.model._3;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import javax.xml.bind.annotation.XmlAccessType;
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
import javax.xml.bind.annotation.XmlAttribute;
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
import javax.xml.bind.annotation.XmlType;
|
import javax.xml.bind.annotation.XmlType;
|
||||||
|
|
||||||
|
|
||||||
@@ -16,6 +19,9 @@ import javax.xml.bind.annotation.XmlType;
|
|||||||
* <complexType name="Application">
|
* <complexType name="Application">
|
||||||
* <complexContent>
|
* <complexContent>
|
||||||
* <extension base="{http://www.alfresco.org/repo/audit/model/3.2}AuditPath">
|
* <extension base="{http://www.alfresco.org/repo/audit/model/3.2}AuditPath">
|
||||||
|
* <sequence>
|
||||||
|
* <element name="PathMappings" type="{http://www.alfresco.org/repo/audit/model/3.2}PathMappings" maxOccurs="unbounded" minOccurs="0"/>
|
||||||
|
* </sequence>
|
||||||
* <attribute name="name" use="required" type="{http://www.alfresco.org/repo/audit/model/3.2}NameAttribute" />
|
* <attribute name="name" use="required" type="{http://www.alfresco.org/repo/audit/model/3.2}NameAttribute" />
|
||||||
* </extension>
|
* </extension>
|
||||||
* </complexContent>
|
* </complexContent>
|
||||||
@@ -25,14 +31,47 @@ import javax.xml.bind.annotation.XmlType;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
@XmlType(name = "Application")
|
@XmlType(name = "Application", propOrder = {
|
||||||
|
"pathMappings"
|
||||||
|
})
|
||||||
public class Application
|
public class Application
|
||||||
extends AuditPath
|
extends AuditPath
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@XmlElement(name = "PathMappings")
|
||||||
|
protected List<PathMappings> pathMappings;
|
||||||
@XmlAttribute(required = true)
|
@XmlAttribute(required = true)
|
||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the pathMappings property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This accessor method returns a reference to the live list,
|
||||||
|
* not a snapshot. Therefore any modification you make to the
|
||||||
|
* returned list will be present inside the JAXB object.
|
||||||
|
* This is why there is not a <CODE>set</CODE> method for the pathMappings property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For example, to add a new item, do as follows:
|
||||||
|
* <pre>
|
||||||
|
* getPathMappings().add(newItem);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Objects of the following type(s) are allowed in the list
|
||||||
|
* {@link PathMappings }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public List<PathMappings> getPathMappings() {
|
||||||
|
if (pathMappings == null) {
|
||||||
|
pathMappings = new ArrayList<PathMappings>();
|
||||||
|
}
|
||||||
|
return this.pathMappings;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of the name property.
|
* Gets the value of the name property.
|
||||||
*
|
*
|
||||||
|
@@ -21,6 +21,7 @@ import javax.xml.bind.annotation.XmlType;
|
|||||||
* <sequence>
|
* <sequence>
|
||||||
* <element name="DataExtractors" type="{http://www.alfresco.org/repo/audit/model/3.2}DataExtractors" minOccurs="0"/>
|
* <element name="DataExtractors" type="{http://www.alfresco.org/repo/audit/model/3.2}DataExtractors" minOccurs="0"/>
|
||||||
* <element name="DataGenerators" type="{http://www.alfresco.org/repo/audit/model/3.2}DataGenerators" minOccurs="0"/>
|
* <element name="DataGenerators" type="{http://www.alfresco.org/repo/audit/model/3.2}DataGenerators" minOccurs="0"/>
|
||||||
|
* <element name="PathMappings" type="{http://www.alfresco.org/repo/audit/model/3.2}PathMappings" minOccurs="0"/>
|
||||||
* <element name="Application" type="{http://www.alfresco.org/repo/audit/model/3.2}Application" maxOccurs="unbounded" minOccurs="0"/>
|
* <element name="Application" type="{http://www.alfresco.org/repo/audit/model/3.2}Application" maxOccurs="unbounded" minOccurs="0"/>
|
||||||
* </sequence>
|
* </sequence>
|
||||||
* </restriction>
|
* </restriction>
|
||||||
@@ -34,6 +35,7 @@ import javax.xml.bind.annotation.XmlType;
|
|||||||
@XmlType(name = "Audit", propOrder = {
|
@XmlType(name = "Audit", propOrder = {
|
||||||
"dataExtractors",
|
"dataExtractors",
|
||||||
"dataGenerators",
|
"dataGenerators",
|
||||||
|
"pathMappings",
|
||||||
"application"
|
"application"
|
||||||
})
|
})
|
||||||
public class Audit {
|
public class Audit {
|
||||||
@@ -42,6 +44,8 @@ public class Audit {
|
|||||||
protected DataExtractors dataExtractors;
|
protected DataExtractors dataExtractors;
|
||||||
@XmlElement(name = "DataGenerators")
|
@XmlElement(name = "DataGenerators")
|
||||||
protected DataGenerators dataGenerators;
|
protected DataGenerators dataGenerators;
|
||||||
|
@XmlElement(name = "PathMappings")
|
||||||
|
protected PathMappings pathMappings;
|
||||||
@XmlElement(name = "Application")
|
@XmlElement(name = "Application")
|
||||||
protected List<Application> application;
|
protected List<Application> application;
|
||||||
|
|
||||||
@@ -93,6 +97,30 @@ public class Audit {
|
|||||||
this.dataGenerators = value;
|
this.dataGenerators = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the pathMappings property.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* possible object is
|
||||||
|
* {@link PathMappings }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public PathMappings getPathMappings() {
|
||||||
|
return pathMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of the pathMappings property.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* allowed object is
|
||||||
|
* {@link PathMappings }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setPathMappings(PathMappings value) {
|
||||||
|
this.pathMappings = value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of the application property.
|
* Gets the value of the application property.
|
||||||
*
|
*
|
||||||
|
@@ -33,14 +33,6 @@ public class ObjectFactory {
|
|||||||
public ObjectFactory() {
|
public ObjectFactory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of {@link RecordValue }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public RecordValue createRecordValue() {
|
|
||||||
return new RecordValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of {@link DataExtractor }
|
* Create an instance of {@link DataExtractor }
|
||||||
*
|
*
|
||||||
@@ -57,6 +49,14 @@ 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 }
|
||||||
*
|
*
|
||||||
@@ -66,19 +66,11 @@ public class ObjectFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of {@link DataGenerator }
|
* Create an instance of {@link PathMap }
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public DataGenerator createDataGenerator() {
|
public PathMap createPathMap() {
|
||||||
return new DataGenerator();
|
return new PathMap();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of {@link DataGenerators }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public DataGenerators createDataGenerators() {
|
|
||||||
return new DataGenerators();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,6 +81,22 @@ public class ObjectFactory {
|
|||||||
return new KeyedAuditDefinition();
|
return new KeyedAuditDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of {@link PathMappings }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public PathMappings createPathMappings() {
|
||||||
|
return new PathMappings();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of {@link DataGenerator }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public DataGenerator createDataGenerator() {
|
||||||
|
return new DataGenerator();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of {@link Application }
|
* Create an instance of {@link Application }
|
||||||
*
|
*
|
||||||
@@ -97,6 +105,14 @@ public class ObjectFactory {
|
|||||||
return new Application();
|
return new Application();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of {@link DataGenerators }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public DataGenerators createDataGenerators() {
|
||||||
|
return new DataGenerators();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of {@link GenerateValue }
|
* Create an instance of {@link GenerateValue }
|
||||||
*
|
*
|
||||||
@@ -106,11 +122,11 @@ public class ObjectFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of {@link DataExtractors }
|
* Create an instance of {@link RecordValue }
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public DataExtractors createDataExtractors() {
|
public RecordValue createRecordValue() {
|
||||||
return new DataExtractors();
|
return new RecordValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
85
source/java/org/alfresco/repo/audit/model/_3/PathMap.java
Normal file
85
source/java/org/alfresco/repo/audit/model/_3/PathMap.java
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
|
||||||
|
package org.alfresco.repo.audit.model._3;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
|
import javax.xml.bind.annotation.XmlType;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Java class for PathMap complex type.
|
||||||
|
*
|
||||||
|
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* <complexType name="PathMap">
|
||||||
|
* <complexContent>
|
||||||
|
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||||
|
* <attribute name="source" use="required" type="{http://www.alfresco.org/repo/audit/model/3.2}PathAttribute" />
|
||||||
|
* <attribute name="target" use="required" type="{http://www.alfresco.org/repo/audit/model/3.2}PathAttribute" />
|
||||||
|
* </restriction>
|
||||||
|
* </complexContent>
|
||||||
|
* </complexType>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
@XmlType(name = "PathMap")
|
||||||
|
public class PathMap {
|
||||||
|
|
||||||
|
@XmlAttribute(required = true)
|
||||||
|
protected String source;
|
||||||
|
@XmlAttribute(required = true)
|
||||||
|
protected String target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the source property.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* possible object is
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public String getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of the source property.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* allowed object is
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setSource(String value) {
|
||||||
|
this.source = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the target property.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* possible object is
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public String getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of the target property.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* allowed object is
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setTarget(String value) {
|
||||||
|
this.target = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
package org.alfresco.repo.audit.model._3;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlType;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Java class for PathMappings complex type.
|
||||||
|
*
|
||||||
|
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* <complexType name="PathMappings">
|
||||||
|
* <complexContent>
|
||||||
|
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||||
|
* <sequence>
|
||||||
|
* <element name="PathMap" type="{http://www.alfresco.org/repo/audit/model/3.2}PathMap" maxOccurs="unbounded" minOccurs="0"/>
|
||||||
|
* </sequence>
|
||||||
|
* </restriction>
|
||||||
|
* </complexContent>
|
||||||
|
* </complexType>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
@XmlType(name = "PathMappings", propOrder = {
|
||||||
|
"pathMap"
|
||||||
|
})
|
||||||
|
public class PathMappings {
|
||||||
|
|
||||||
|
@XmlElement(name = "PathMap")
|
||||||
|
protected List<PathMap> pathMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the pathMap property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This accessor method returns a reference to the live list,
|
||||||
|
* not a snapshot. Therefore any modification you make to the
|
||||||
|
* returned list will be present inside the JAXB object.
|
||||||
|
* This is why there is not a <CODE>set</CODE> method for the pathMap property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For example, to add a new item, do as follows:
|
||||||
|
* <pre>
|
||||||
|
* getPathMap().add(newItem);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Objects of the following type(s) are allowed in the list
|
||||||
|
* {@link PathMap }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public List<PathMap> getPathMap() {
|
||||||
|
if (pathMap == null) {
|
||||||
|
pathMap = new ArrayList<PathMap>();
|
||||||
|
}
|
||||||
|
return this.pathMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -19,6 +19,13 @@
|
|||||||
<DataGenerator name="user" class="org.alfresco.repo.audit.generator.AuthenticatedUserDataGenerator"/>
|
<DataGenerator name="user" class="org.alfresco.repo.audit.generator.AuthenticatedUserDataGenerator"/>
|
||||||
</DataGenerators>
|
</DataGenerators>
|
||||||
|
|
||||||
|
<PathMappings>
|
||||||
|
<PathMap source="/test/one.one/two.one" target="/test/1.1/2.1"/>
|
||||||
|
<PathMap source="/test/one.one/two.two" target="/test/1.1/2.2"/>
|
||||||
|
<PathMap source="/actions-test" target="/actions-test"/>
|
||||||
|
<PathMap source="/actions-test/actions/action-01-mapped" target="/actions-test/actions/action-01"/>
|
||||||
|
</PathMappings>
|
||||||
|
|
||||||
<Application name="Alfresco Test" key="test">
|
<Application name="Alfresco Test" key="test">
|
||||||
<GenerateValue key="time" dataGenerator="systemTime"/>
|
<GenerateValue key="time" dataGenerator="systemTime"/>
|
||||||
<AuditPath key="1.1">
|
<AuditPath key="1.1">
|
||||||
|
Reference in New Issue
Block a user