diff --git a/config/alfresco/bulk-import-context.xml b/config/alfresco/bulk-import-context.xml
index f1ebeaa955..aeb4d9a376 100644
--- a/config/alfresco/bulk-import-context.xml
+++ b/config/alfresco/bulk-import-context.xml
@@ -47,6 +47,7 @@
+
diff --git a/source/java/org/alfresco/repo/batch/BatchProcessor.java b/source/java/org/alfresco/repo/batch/BatchProcessor.java
index cc5f5ce66e..738d456c63 100644
--- a/source/java/org/alfresco/repo/batch/BatchProcessor.java
+++ b/source/java/org/alfresco/repo/batch/BatchProcessor.java
@@ -37,6 +37,7 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.TransactionListenerAdapter;
@@ -773,12 +774,13 @@ public class BatchProcessor implements BatchMonitor
if (this.splitTxns)
{
this.txnLastError = t;
- this.txnLastErrorEntryId = this.txnEntryId;
+ this.txnLastErrorEntryId = (t instanceof IntegrityException) ? "unknown" : this.txnEntryId;
this.txnErrors++;
if (BatchProcessor.this.logger.isWarnEnabled())
{
- BatchProcessor.this.logger.warn(getProcessName() + ": Failed to process entry \""
- + BatchProcessor.this.currentEntryId + "\".", t);
+ String message = (t instanceof IntegrityException) ? ": Failed on batch commit." : ": Failed to process entry \""
+ + this.txnEntryId + "\".";
+ BatchProcessor.this.logger.warn(getProcessName() + message, t);
}
}
// Otherwise, we have a retryable exception that we should propagate
diff --git a/source/java/org/alfresco/repo/bulkimport/impl/DirectoryAnalyserImpl.java b/source/java/org/alfresco/repo/bulkimport/impl/DirectoryAnalyserImpl.java
index e63d723ee4..58538def7d 100644
--- a/source/java/org/alfresco/repo/bulkimport/impl/DirectoryAnalyserImpl.java
+++ b/source/java/org/alfresco/repo/bulkimport/impl/DirectoryAnalyserImpl.java
@@ -27,13 +27,16 @@ package org.alfresco.repo.bulkimport.impl;
import java.io.File;
import java.io.FileFilter;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.bulkimport.AnalysedDirectory;
import org.alfresco.repo.bulkimport.DirectoryAnalyser;
import org.alfresco.repo.bulkimport.ImportFilter;
@@ -41,7 +44,12 @@ import org.alfresco.repo.bulkimport.ImportableItem;
import org.alfresco.repo.bulkimport.ImportableItem.FileType;
import org.alfresco.repo.bulkimport.MetadataLoader;
import org.alfresco.repo.dictionary.constraint.NameChecker;
+import org.alfresco.service.cmr.dictionary.Constraint;
+import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintException;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.dictionary.PropertyDefinition;
+import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO8601DateFormat;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -64,6 +72,7 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser
private BulkImportStatusImpl importStatus;
private List importFilters;
private NameChecker nameChecker;
+ private DictionaryService dictionaryService;
public DirectoryAnalyserImpl(MetadataLoader metadataLoader, BulkImportStatusImpl importStatus, List importFilters,
@@ -79,6 +88,11 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser
{
}
+ public void setDictionaryService(DictionaryService dictionaryService)
+ {
+ this.dictionaryService = dictionaryService;
+ }
+
public void setNameChecker(NameChecker nameChecker)
{
this.nameChecker = nameChecker;
@@ -230,7 +244,7 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser
{
ImportableItem importableItem = iter.next();
- if (!importableItem.isValid())
+ if (!importableItem.isValid() || !isMetadataValid(importableItem))
{
iter.remove();
}
@@ -255,6 +269,51 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser
return result;
}
+ private boolean isMetadataValid(ImportableItem importableItem)
+ {
+ if (!importableItem.getHeadRevision().metadataFileExists())
+ {
+ return true;
+ }
+
+ if (metadataLoader != null)
+ {
+ MetadataLoader.Metadata result = new MetadataLoader.Metadata();
+ metadataLoader.loadMetadata(importableItem.getHeadRevision(), result);
+
+ Map metadataProperties = result.getProperties();
+ for (QName propertyName : metadataProperties.keySet())
+ {
+ PropertyDefinition propDef = dictionaryService.getProperty(propertyName);
+ if (propDef != null)
+ {
+ for (ConstraintDefinition constraintDef : propDef.getConstraints())
+ {
+ Constraint constraint = constraintDef.getConstraint();
+ if (constraint != null)
+ {
+ try
+ {
+ constraint.evaluate(metadataProperties.get(propertyName));
+ }
+ catch (ConstraintException e)
+ {
+ if (log.isWarnEnabled())
+ {
+ log.warn("Skipping file '" + FileUtils.getFileName(importableItem.getHeadRevision().getContentFile())
+ +"' with invalid metadata: '" + FileUtils.getFileName(importableItem.getHeadRevision().getMetadataFile()) + "'.", e);
+ }
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
private boolean isVersionFile(File file)
{
Matcher matcher = VERSION_SUFFIX_PATTERN.matcher(file.getName());
diff --git a/source/java/org/alfresco/repo/node/integrity/PropertiesIntegrityEvent.java b/source/java/org/alfresco/repo/node/integrity/PropertiesIntegrityEvent.java
index e6ad0cfaf5..fd68fa7077 100644
--- a/source/java/org/alfresco/repo/node/integrity/PropertiesIntegrityEvent.java
+++ b/source/java/org/alfresco/repo/node/integrity/PropertiesIntegrityEvent.java
@@ -153,9 +153,11 @@ public class PropertiesIntegrityEvent extends AbstractIntegrityEvent
// check that enforced, mandatoryproperties are set
if (propertyDef.isMandatory() && propertyDef.isMandatoryEnforced() && !nodeProperties.containsKey(propertyQName))
{
+ String nameProp = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
IntegrityRecord result = new IntegrityRecord(
"Mandatory property not set: \n" +
" Node: " + nodeRef + "\n" +
+ (nameProp != null ? " Name: " + nameProp + "\n" : "") +
" Type: " + typeQName + "\n" +
" Property: " + propertyQName);
eventResults.add(result);
@@ -168,9 +170,11 @@ public class PropertiesIntegrityEvent extends AbstractIntegrityEvent
{
if (propertyValue != null && !(propertyValue instanceof SealedObject))
{
+ String nameProp = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
IntegrityRecord result = new IntegrityRecord(
"Property must be encrypted: \n" +
" Node: " + nodeRef + "\n" +
+ (nameProp != null ? " Name: " + nameProp + "\n" : "") +
" Type: " + typeQName + "\n" +
" Property: " + propertyQName);
eventResults.add(result);
@@ -188,9 +192,11 @@ public class PropertiesIntegrityEvent extends AbstractIntegrityEvent
}
catch (ConstraintException e)
{
+ String nameProp = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
IntegrityRecord result = new IntegrityRecord(
"Invalid property value: \n" +
" Node: " + nodeRef + "\n" +
+ (nameProp != null ? " Name: " + nameProp + "\n" : "") +
" Type: " + typeQName + "\n" +
" Property: " + propertyQName + "\n" +
" Constraint: " + e.getMessage());