Added a registry for DataExtractors and DataGenerators

- Uses recently-added NamedObjectRegistry
 - Audit extractors and generators can now be Sprung using 'registeredName' instead of 'class'
 - Simpler to bring in complex, repo-dependent generators and extractors


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@15935 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2009-08-26 16:43:40 +00:00
parent de4467b12d
commit b57ae75eff
12 changed files with 378 additions and 120 deletions

View File

@@ -58,7 +58,7 @@ public class AuditBootstrapTest extends TestCase
@Override
public void setUp() throws Exception
{
auditModelRegistry = (AuditModelRegistry) ctx.getBean("auditModel.registry");
auditModelRegistry = (AuditModelRegistry) ctx.getBean("auditModel.modelRegistry");
// Register a new model
URL testModelUrl = ResourceUtils.getURL("classpath:alfresco/audit/alfresco-audit-test.xml");

View File

@@ -26,6 +26,7 @@ package org.alfresco.repo.audit;
import java.io.Serializable;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -63,7 +64,7 @@ public class AuditComponentTest extends TestCase
@Override
public void setUp() throws Exception
{
auditModelRegistry = (AuditModelRegistry) ctx.getBean("auditModel.registry");
auditModelRegistry = (AuditModelRegistry) ctx.getBean("auditModel.modelRegistry");
auditComponent = (AuditComponent) ctx.getBean("auditComponent");
transactionService = (TransactionService) ctx.getBean("transactionService");
@@ -71,6 +72,15 @@ public class AuditComponentTest extends TestCase
URL testModelUrl = ResourceUtils.getURL("classpath:alfresco/audit/alfresco-audit-test.xml");
auditModelRegistry.registerModel(testModelUrl);
auditModelRegistry.loadAuditModels();
// Authenticate
AuthenticationUtil.setFullyAuthenticatedUser("User-" + getName() + System.currentTimeMillis());
}
@Override
public void tearDown() throws Exception
{
AuthenticationUtil.clearCurrentSecurityContext();
}
public void testSetUp()
@@ -126,7 +136,7 @@ public class AuditComponentTest extends TestCase
/**
* Start a session and use it within a single txn
*/
public void testBasicSession() throws Exception
public void testSession_Basic() throws Exception
{
final RetryingTransactionCallback<Void> testCallback = new RetryingTransactionCallback<Void>()
{
@@ -137,6 +147,7 @@ public class AuditComponentTest extends TestCase
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.2", "42");
values.put("/test/1.1/2.1/3.1/4.2", new Date());
auditComponent.audit(session, values);
@@ -150,6 +161,37 @@ public class AuditComponentTest extends TestCase
return transactionService.getRetryingTransactionHelper().doInTransaction(testCallback);
}
};
AuthenticationUtil.runAs(testRunAs, "Peanut");
AuthenticationUtil.runAs(testRunAs, "SomeOtherUser");
}
/**
* Start a session and use it within a single txn
*/
public void testSession_Extended01() throws Exception
{
final RetryingTransactionCallback<Void> testCallback = new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
AuditSession session = auditComponent.startAuditSession(APPLICATION_TEST, "/test/1.1");
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.2", "42");
values.put("/test/1.1/2.1/3.1/4.2", new Date());
auditComponent.audit(session, values);
return null;
}
};
RunAsWork<Void> testRunAs = new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
return transactionService.getRetryingTransactionHelper().doInTransaction(testCallback);
}
};
AuthenticationUtil.runAs(testRunAs, "SomeOtherUser");
}
}

View File

@@ -24,14 +24,51 @@
*/
package org.alfresco.repo.audit.extractor;
import org.alfresco.util.PropertyCheck;
import org.alfresco.util.registry.NamedObjectRegistry;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
/**
* Abstract implementation to provide support.
*
* @author Derek Hulley
* @since 3.2
*/
public abstract class AbstractDataExtractor implements DataExtractor
public abstract class AbstractDataExtractor implements DataExtractor, InitializingBean, BeanNameAware
{
private String name;
private NamedObjectRegistry<DataExtractor> registry;
/**
* Set the name with which to {@link #setRegistry(NamedObjectRegistry) register}
* @param name the name of the bean
*/
public void setBeanName(String name)
{
this.name = name;
}
/**
* Set the registry with which to register
* @param registry
*/
public void setRegistry(NamedObjectRegistry<DataExtractor> registry)
{
this.registry = registry;
}
/**
* Registers the instance
*/
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "name", name);
PropertyCheck.mandatory(this, "registry", registry);
registry.register(name, this);
}
/**
* This implementation assumes all extractors are stateless i.e. if the class matches
* then the instances are equal.

View File

@@ -24,14 +24,51 @@
*/
package org.alfresco.repo.audit.generator;
import org.alfresco.util.PropertyCheck;
import org.alfresco.util.registry.NamedObjectRegistry;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
/**
* Abstract implementation to provide support.
*
* @author Derek Hulley
* @since 3.2
*/
public abstract class AbstractDataGenerator implements DataGenerator
public abstract class AbstractDataGenerator implements DataGenerator, InitializingBean, BeanNameAware
{
private String name;
private NamedObjectRegistry<DataGenerator> registry;
/**
* Set the name with which to {@link #setRegistry(NamedObjectRegistry) register}
* @param name the name of the bean
*/
public void setBeanName(String name)
{
this.name = name;
}
/**
* Set the registry with which to register
* @param registry
*/
public void setRegistry(NamedObjectRegistry<DataGenerator> registry)
{
this.registry = registry;
}
/**
* Registers the instance
*/
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "name", name);
PropertyCheck.mandatory(this, "registry", registry);
registry.register(name, this);
}
/**
* This implementation assumes all generators are stateless i.e. if the class matches
* then the instances are equal.

View File

@@ -58,6 +58,8 @@ import org.alfresco.repo.domain.audit.AuditDAO;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.PropertyCheck;
import org.alfresco.util.registry.NamedObjectRegistry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.ResourceUtils;
@@ -80,6 +82,8 @@ public class AuditModelRegistry
private TransactionService transactionService;
private AuditDAO auditDAO;
private NamedObjectRegistry<DataExtractor> dataExtractors;
private NamedObjectRegistry<DataGenerator> dataGenerators;
private final ReentrantReadWriteLock.ReadLock readLock;
private final ReentrantReadWriteLock.WriteLock writeLock;
@@ -87,8 +91,6 @@ public class AuditModelRegistry
private final Set<URL> auditModelUrls;
private final List<Audit> auditModels;
private final Map<String, DataExtractor> dataExtractorsByName;
private final Map<String, DataGenerator> dataGeneratorsByName;
/**
* Used to lookup the audit application java hierarchy
*/
@@ -111,8 +113,6 @@ public class AuditModelRegistry
auditModelUrls = new HashSet<URL>(7);
auditModels = new ArrayList<Audit>(7);
dataExtractorsByName = new HashMap<String, DataExtractor>(13);
dataGeneratorsByName = new HashMap<String, DataGenerator>(13);
auditApplicationsByName = new HashMap<String, AuditApplication>(7);
auditModelIdsByApplicationsName = new HashMap<String, Long>(7);
}
@@ -133,6 +133,33 @@ public class AuditModelRegistry
this.auditDAO = auditDAO;
}
/**
* Set the registry of {@link DataExtractor data extractors}
*/
public void setDataExtractors(NamedObjectRegistry<DataExtractor> dataExtractors)
{
this.dataExtractors = dataExtractors;
}
/**
* Set the registry of {@link DataGenerator data generators}
*/
public void setDataGenerators(NamedObjectRegistry<DataGenerator> dataGenerators)
{
this.dataGenerators = dataGenerators;
}
/**
* Ensures that all properties have been set for use.
*/
private void checkProperties()
{
PropertyCheck.mandatory(this, "transactionService", transactionService);
PropertyCheck.mandatory(this, "auditDAO", auditDAO);
PropertyCheck.mandatory(this, "dataExtractors", dataExtractors);
PropertyCheck.mandatory(this, "dataGenerators", dataGenerators);
}
/**
* Register an audit model at a given URL.
*
@@ -140,6 +167,7 @@ public class AuditModelRegistry
*/
public void registerModel(URL auditModelUrl)
{
checkProperties();
writeLock.lock();
try
{
@@ -162,6 +190,7 @@ public class AuditModelRegistry
*/
public void registerModel(NodeRef auditModelNodeRef)
{
checkProperties();
writeLock.lock();
try
{
@@ -179,8 +208,6 @@ public class AuditModelRegistry
private void clearCaches()
{
auditModels.clear();
dataExtractorsByName.clear();
dataGeneratorsByName.clear();;
auditApplicationsByName.clear();
auditModelIdsByApplicationsName.clear();
}
@@ -194,6 +221,8 @@ public class AuditModelRegistry
*/
public void loadAuditModels()
{
checkProperties();
RetryingTransactionCallback<Void> loadModelsCallback = new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
@@ -365,42 +394,58 @@ public class AuditModelRegistry
private void cacheAuditElements(Long auditModelId, Audit audit)
{
Map<String, DataExtractor> dataExtractorsByName = new HashMap<String, DataExtractor>(13);
Map<String, DataGenerator> dataGeneratorsByName = new HashMap<String, DataGenerator>(13);
// Get the data extractors and check for duplicates
DataExtractors extractorsElement = audit.getDataExtractors();
if (extractorsElement == null)
{
extractorsElement = objectFactory.createDataExtractors();
}
List<org.alfresco.repo.audit.model._3.DataExtractor> converterElements = extractorsElement.getDataExtractor();
for (org.alfresco.repo.audit.model._3.DataExtractor converterElement : converterElements)
List<org.alfresco.repo.audit.model._3.DataExtractor> extractorElements = extractorsElement.getDataExtractor();
for (org.alfresco.repo.audit.model._3.DataExtractor extractorElement : extractorElements)
{
String name = converterElement.getName();
// Construct the converter
final DataExtractor dataExtractor;
try
{
Class<?> dataExtractorClazz = Class.forName(converterElement.getClazz());
dataExtractor = (DataExtractor) dataExtractorClazz.newInstance();
}
catch (ClassNotFoundException e)
{
throw new AuditModelException(
"Audit data extractor '" + name + "' class not found: " + converterElement.getClazz());
}
catch (Exception e)
{
throw new AuditModelException(
"Audit data extractor '" + name + "' could not be constructed: " + converterElement.getClazz());
}
String name = extractorElement.getName();
// If the name is taken, make sure that they are equal
if (dataExtractorsByName.containsKey(name))
{
DataExtractor existing = dataExtractorsByName.get(name);
if (!existing.equals(dataExtractor))
throw new AuditModelException(
"Audit data extractor '" + name + "' has already been defined.");
}
// Construct the converter
final DataExtractor dataExtractor;
if (extractorElement.getClazz() != null)
{
try
{
Class<?> dataExtractorClazz = Class.forName(extractorElement.getClazz());
dataExtractor = (DataExtractor) dataExtractorClazz.newInstance();
}
catch (ClassNotFoundException e)
{
throw new AuditModelException(
"Audit data extractor '" + name + "' is incompatible with an existing instance.");
"Audit data extractor '" + name + "' class not found: " + extractorElement.getClazz());
}
catch (Exception e)
{
throw new AuditModelException(
"Audit data extractor '" + name + "' could not be constructed: " + extractorElement.getClazz());
}
}
else if (extractorElement.getRegisteredName() != null)
{
dataExtractor = dataExtractors.getNamedObject(extractorElement.getRegisteredName());
if (dataExtractor == null)
{
throw new AuditModelException(
"No registered audit data extractor exists for '" + name + "'.");
}
}
else
{
throw new AuditModelException(
"Audit data extractor has no class or registered name: " + name);
}
// Store
dataExtractorsByName.put(name, dataExtractor);
@@ -415,32 +460,45 @@ public class AuditModelRegistry
for (org.alfresco.repo.audit.model._3.DataGenerator generatorElement : generatorElements)
{
String name = generatorElement.getName();
// Construct the converter
final DataGenerator dataGenerator;
try
{
Class<?> dataExtractorClazz = Class.forName(generatorElement.getClazz());
dataGenerator = (DataGenerator) dataExtractorClazz.newInstance();
}
catch (ClassNotFoundException e)
{
throw new AuditModelException(
"Audit data generator '" + name + "' class not found: " + generatorElement.getClazz());
}
catch (Exception e)
{
throw new AuditModelException(
"Audit data generator '" + name + "' could not be constructed: " + generatorElement.getClazz());
}
// If the name is taken, make sure that they are equal
if (dataGeneratorsByName.containsKey(name))
{
DataGenerator existing = dataGeneratorsByName.get(name);
if (!existing.equals(dataGenerator))
throw new AuditModelException(
"Audit data generator '" + name + "' has already been defined.");
}
// Construct the generator
final DataGenerator dataGenerator;
if (generatorElement.getClazz() != null)
{
try
{
Class<?> dataGeneratorClazz = Class.forName(generatorElement.getClazz());
dataGenerator = (DataGenerator) dataGeneratorClazz.newInstance();
}
catch (ClassNotFoundException e)
{
throw new AuditModelException(
"Audit data generator '" + name + "' is incompatible with an existing instance.");
"Audit data generator '" + name + "' class not found: " + generatorElement.getClazz());
}
catch (Exception e)
{
throw new AuditModelException(
"Audit data generator '" + name + "' could not be constructed: " + generatorElement.getClazz());
}
}
else if (generatorElement.getRegisteredName() != null)
{
dataGenerator = dataGenerators.getNamedObject(generatorElement.getRegisteredName());
if (dataGenerator == null)
{
throw new AuditModelException(
"No registered audit data generator exists for '" + name + "'.");
}
}
else
{
throw new AuditModelException(
"Audit data generator has no class or registered name: " + name);
}
// Store
dataGeneratorsByName.put(name, dataGenerator);

View File

@@ -16,7 +16,8 @@ import javax.xml.bind.annotation.XmlType;
* &lt;complexType name="DataExtractor">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;attribute name="name" type="{http://www.alfresco.org/repo/audit/model/3.2}NameAttribute" />
* &lt;attribute name="name" use="required" type="{http://www.alfresco.org/repo/audit/model/3.2}NameAttribute" />
* &lt;attribute name="registeredName" type="{http://www.alfresco.org/repo/audit/model/3.2}NameAttribute" />
* &lt;attribute name="class" type="{http://www.alfresco.org/repo/audit/model/3.2}ClassAttribute" />
* &lt;/restriction>
* &lt;/complexContent>
@@ -29,8 +30,10 @@ import javax.xml.bind.annotation.XmlType;
@XmlType(name = "DataExtractor")
public class DataExtractor {
@XmlAttribute
@XmlAttribute(required = true)
protected String name;
@XmlAttribute
protected String registeredName;
@XmlAttribute(name = "class")
protected String clazz;
@@ -58,6 +61,30 @@ public class DataExtractor {
this.name = value;
}
/**
* Gets the value of the registeredName property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getRegisteredName() {
return registeredName;
}
/**
* Sets the value of the registeredName property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setRegisteredName(String value) {
this.registeredName = value;
}
/**
* Gets the value of the clazz property.
*

View File

@@ -16,7 +16,8 @@ import javax.xml.bind.annotation.XmlType;
* &lt;complexType name="DataGenerator">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;attribute name="name" type="{http://www.alfresco.org/repo/audit/model/3.2}NameAttribute" />
* &lt;attribute name="name" use="required" type="{http://www.alfresco.org/repo/audit/model/3.2}NameAttribute" />
* &lt;attribute name="registeredName" type="{http://www.alfresco.org/repo/audit/model/3.2}NameAttribute" />
* &lt;attribute name="class" type="{http://www.alfresco.org/repo/audit/model/3.2}ClassAttribute" />
* &lt;/restriction>
* &lt;/complexContent>
@@ -29,8 +30,10 @@ import javax.xml.bind.annotation.XmlType;
@XmlType(name = "DataGenerator")
public class DataGenerator {
@XmlAttribute
@XmlAttribute(required = true)
protected String name;
@XmlAttribute
protected String registeredName;
@XmlAttribute(name = "class")
protected String clazz;
@@ -58,6 +61,30 @@ public class DataGenerator {
this.name = value;
}
/**
* Gets the value of the registeredName property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getRegisteredName() {
return registeredName;
}
/**
* Sets the value of the registeredName property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setRegisteredName(String value) {
this.registeredName = value;
}
/**
* Gets the value of the clazz property.
*

View File

@@ -34,51 +34,11 @@ public class ObjectFactory {
}
/**
* Create an instance of {@link KeyedAuditDefinition }
* Create an instance of {@link Application }
*
*/
public KeyedAuditDefinition createKeyedAuditDefinition() {
return new KeyedAuditDefinition();
}
/**
* Create an instance of {@link DataExtractor }
*
*/
public DataExtractor createDataExtractor() {
return new DataExtractor();
}
/**
* Create an instance of {@link Audit }
*
*/
public Audit createAudit() {
return new Audit();
}
/**
* Create an instance of {@link DataExtractors }
*
*/
public DataExtractors createDataExtractors() {
return new DataExtractors();
}
/**
* Create an instance of {@link AuditPath }
*
*/
public AuditPath createAuditPath() {
return new AuditPath();
}
/**
* Create an instance of {@link DataGenerator }
*
*/
public DataGenerator createDataGenerator() {
return new DataGenerator();
public Application createApplication() {
return new Application();
}
/**
@@ -89,6 +49,22 @@ public class ObjectFactory {
return new DataGenerators();
}
/**
* Create an instance of {@link DataExtractor }
*
*/
public DataExtractor createDataExtractor() {
return new DataExtractor();
}
/**
* Create an instance of {@link AuditPath }
*
*/
public AuditPath createAuditPath() {
return new AuditPath();
}
/**
* Create an instance of {@link RecordValue }
*
@@ -97,14 +73,6 @@ public class ObjectFactory {
return new RecordValue();
}
/**
* Create an instance of {@link Application }
*
*/
public Application createApplication() {
return new Application();
}
/**
* Create an instance of {@link GenerateValue }
*
@@ -113,6 +81,38 @@ public class ObjectFactory {
return new GenerateValue();
}
/**
* Create an instance of {@link Audit }
*
*/
public Audit createAudit() {
return new Audit();
}
/**
* Create an instance of {@link KeyedAuditDefinition }
*
*/
public KeyedAuditDefinition createKeyedAuditDefinition() {
return new KeyedAuditDefinition();
}
/**
* Create an instance of {@link DataExtractors }
*
*/
public DataExtractors createDataExtractors() {
return new DataExtractors();
}
/**
* Create an instance of {@link DataGenerator }
*
*/
public DataGenerator createDataGenerator() {
return new DataGenerator();
}
/**
* Create an instance of {@link JAXBElement }{@code <}{@link Audit }{@code >}}
*