MNT-17703: Allow Bulk Import versioning without appending a version number to docs

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@136971 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Matt Ward
2017-05-26 15:55:40 +00:00
parent b930f7ca56
commit 64a0f743a2
17 changed files with 482 additions and 234 deletions

View File

@@ -29,8 +29,17 @@ import org.alfresco.service.cmr.repository.NodeRef;
public class BulkImportParameters public class BulkImportParameters
{ {
// MNT-17703: Provide configurable behaviour for when the target file already exists in the repository.
public enum ExistingFileMode
{
// If the file already exists...
SKIP, // skip the import from the source.
REPLACE, // replace the file, loosing any previous version history.
ADD_VERSION // create a new version of the file during import, preserving previous history.
};
private ExistingFileMode existingFileMode = ExistingFileMode.SKIP;
private NodeRef target; private NodeRef target;
private boolean replaceExisting = false;
private Integer batchSize; private Integer batchSize;
private Integer numThreads; private Integer numThreads;
private Integer loggingInterval; private Integer loggingInterval;
@@ -60,14 +69,6 @@ public class BulkImportParameters
{ {
this.target = target; this.target = target;
} }
public boolean isReplaceExisting()
{
return replaceExisting;
}
public void setReplaceExisting(boolean replaceExisting)
{
this.replaceExisting = replaceExisting;
}
public Integer getBatchSize() public Integer getBatchSize()
{ {
return batchSize; return batchSize;
@@ -85,4 +86,39 @@ public class BulkImportParameters
this.numThreads = numThreads; this.numThreads = numThreads;
} }
/**
* @deprecated Use {@link #getExistingFileMode} (MNT-17703)
* @return
*/
public boolean isReplaceExisting()
{
return existingFileMode == ExistingFileMode.REPLACE;
}
/**
* @deprecated Use {@link #setExistingFileMode} (MNT-17703)
* @param replaceExisting
*/
@Deprecated()
public void setReplaceExisting(boolean replaceExisting)
{
if (replaceExisting)
{
setExistingFileMode(ExistingFileMode.REPLACE);
}
else
{
setExistingFileMode(ExistingFileMode.SKIP);
}
}
public ExistingFileMode getExistingFileMode()
{
return existingFileMode;
}
public void setExistingFileMode(ExistingFileMode existingFileMode)
{
this.existingFileMode = existingFileMode;
}
} }

View File

@@ -120,6 +120,10 @@ public final class ImportableItem
public Set<VersionedContentAndMetadata> getVersionEntries() public Set<VersionedContentAndMetadata> getVersionEntries()
{ {
if (versionEntries == null)
{
return Collections.emptySet();
}
return(Collections.unmodifiableSet(versionEntries)); return(Collections.unmodifiableSet(versionEntries));
} }

View File

@@ -37,6 +37,6 @@ import org.alfresco.service.cmr.repository.NodeRef;
*/ */
public interface NodeImporter public interface NodeImporter
{ {
public NodeRef importImportableItem(ImportableItem importableItem, boolean replaceExisting); public NodeRef importImportableItem(ImportableItem importableItem, BulkImportParameters.ExistingFileMode existingFileMode);
public File getSourceFolder(); public File getSourceFolder();
} }

View File

@@ -33,6 +33,7 @@ import java.util.Map;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.bulkimport.BulkFilesystemImporter; import org.alfresco.repo.bulkimport.BulkFilesystemImporter;
import org.alfresco.repo.bulkimport.BulkImportParameters;
import org.alfresco.repo.bulkimport.DirectoryAnalyser; import org.alfresco.repo.bulkimport.DirectoryAnalyser;
import org.alfresco.repo.bulkimport.ImportableItem; import org.alfresco.repo.bulkimport.ImportableItem;
import org.alfresco.repo.bulkimport.MetadataLoader; import org.alfresco.repo.bulkimport.MetadataLoader;
@@ -99,7 +100,7 @@ public abstract class AbstractNodeImporter implements NodeImporter
this.behaviourFilter = behaviourFilter; this.behaviourFilter = behaviourFilter;
} }
protected abstract NodeRef importImportableItemImpl(ImportableItem importableItem, boolean replaceExisting); protected abstract NodeRef importImportableItemImpl(ImportableItem importableItem, BulkImportParameters.ExistingFileMode existingFileMode);
protected abstract void importContentAndMetadata(NodeRef nodeRef, ImportableItem.ContentAndMetadata contentAndMetadata, MetadataLoader.Metadata metadata); protected abstract void importContentAndMetadata(NodeRef nodeRef, ImportableItem.ContentAndMetadata contentAndMetadata, MetadataLoader.Metadata metadata);
/* /*
@@ -181,11 +182,19 @@ public abstract class AbstractNodeImporter implements NodeImporter
return(result); return(result);
} }
protected final int importImportableItemFile(NodeRef nodeRef, ImportableItem importableItem, MetadataLoader.Metadata metadata, NodeState nodeState) protected final int importImportableItemFile(NodeRef nodeRef, ImportableItem importableItem, MetadataLoader.Metadata metadata, NodeState nodeState, BulkImportParameters.ExistingFileMode existingFileMode)
{ {
int result = 0; int result = 0;
if (importableItem.hasVersionEntries()) if (nodeState == NodeState.REPLACED && existingFileMode == BulkImportParameters.ExistingFileMode.ADD_VERSION)
{
// It is being replaced, and ADD_VERSION is the selected method of dealing with overwrites.
Map<QName, Serializable> versionProperties = new HashMap<>();
versionProperties.put(ContentModel.PROP_VERSION_TYPE, VersionType.MAJOR);
versionService.ensureVersioningEnabled(nodeRef, versionProperties);
result = importContentVersions(nodeRef, importableItem, nodeState);
}
else if (importableItem.hasVersionEntries())
{ {
result = importContentVersions(nodeRef, importableItem, nodeState); result = importContentVersions(nodeRef, importableItem, nodeState);
} }
@@ -242,9 +251,18 @@ public abstract class AbstractNodeImporter implements NodeImporter
return(result); return(result);
} }
protected final Triple<NodeRef, Boolean, NodeState> createOrFindNode(NodeRef target, ImportableItem importableItem, // TODO: this is a confusing method that does too many things. It doesn't just "create or find"
boolean replaceExisting, MetadataLoader.Metadata metadata) // but also decides whether an existing node (i.e. the 'find' in 'create or find') WILL BE
// skipped or replaced further on in the calling code.
// TODO: refactor?
protected final Triple<NodeRef, Boolean, NodeState> createOrFindNode(
NodeRef target, ImportableItem importableItem,
BulkImportParameters.ExistingFileMode existingFileMode, MetadataLoader.Metadata metadata)
{ {
// ADD_VERSION isn't strictly a replacement option, but we need to deal with it as such, at least as an
// interim measure while the new ExistingFileMode options are introduced (MNT-17703)
boolean replaceExisting = (existingFileMode == BulkImportParameters.ExistingFileMode.REPLACE ||
existingFileMode == BulkImportParameters.ExistingFileMode.ADD_VERSION);
Triple<NodeRef, Boolean, NodeState> result = null; Triple<NodeRef, Boolean, NodeState> result = null;
boolean isDirectory = false; boolean isDirectory = false;
NodeState nodeState = replaceExisting ? NodeState.REPLACED : NodeState.SKIPPED; NodeState nodeState = replaceExisting ? NodeState.REPLACED : NodeState.SKIPPED;
@@ -424,14 +442,14 @@ public abstract class AbstractNodeImporter implements NodeImporter
return(result); return(result);
} }
public NodeRef importImportableItem(ImportableItem importableItem, boolean replaceExisting) public NodeRef importImportableItem(ImportableItem importableItem, BulkImportParameters.ExistingFileMode existingFileMode)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Importing " + String.valueOf(importableItem)); logger.debug("Importing " + String.valueOf(importableItem));
} }
NodeRef nodeRef = importImportableItemImpl(importableItem, replaceExisting); NodeRef nodeRef = importImportableItemImpl(importableItem, existingFileMode);
// allow parent to be garbage collected // allow parent to be garbage collected
//importableItem.setParent(null); //importableItem.setParent(null);

View File

@@ -126,7 +126,7 @@ public abstract class MultiThreadedBulkFilesystemImporter extends AbstractBulkFi
{ {
behaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE); behaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
NodeRef nodeRef = nodeImporter.importImportableItem(importableItem, bulkImportParameters.isReplaceExisting()); NodeRef nodeRef = nodeImporter.importImportableItem(importableItem, bulkImportParameters.getExistingFileMode());
filesystemTracker.itemImported(nodeRef, importableItem); filesystemTracker.itemImported(nodeRef, importableItem);
} }
finally finally

View File

@@ -30,6 +30,7 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.bulkimport.BulkImportParameters;
import org.alfresco.repo.bulkimport.ImportableItem; import org.alfresco.repo.bulkimport.ImportableItem;
import org.alfresco.repo.bulkimport.MetadataLoader; import org.alfresco.repo.bulkimport.MetadataLoader;
import org.alfresco.repo.bulkimport.NodeImporter; import org.alfresco.repo.bulkimport.NodeImporter;
@@ -109,7 +110,7 @@ public class StreamingNodeImporterFactory extends AbstractNodeImporterFactory
importImportableItemMetadata(nodeRef, contentAndMetadata.getContentFile(), metadata); importImportableItemMetadata(nodeRef, contentAndMetadata.getContentFile(), metadata);
} }
protected NodeRef importImportableItemImpl(ImportableItem importableItem, boolean replaceExisting) protected NodeRef importImportableItemImpl(ImportableItem importableItem, BulkImportParameters.ExistingFileMode existingFileMode)
{ {
NodeRef target = importableItem.getParent().getNodeRef(); NodeRef target = importableItem.getParent().getNodeRef();
if(target == null) if(target == null)
@@ -120,7 +121,16 @@ public class StreamingNodeImporterFactory extends AbstractNodeImporterFactory
NodeRef result = null; NodeRef result = null;
MetadataLoader.Metadata metadata = loadMetadata(importableItem.getHeadRevision()); MetadataLoader.Metadata metadata = loadMetadata(importableItem.getHeadRevision());
Triple<NodeRef, Boolean, NodeState> node = createOrFindNode(target, importableItem, replaceExisting, metadata); // TODO: we'll get NodeState.REPLACED back from this method (i.e. the node WILL be replaced)
// even if we're using ExistingFileMode.ADD_VERSION - we need to do this currently, otherwise
// the file would be SKIPPED and various other checks that are only computed if replace is being used,
// wouldn't happen.
// TODO: sort this out.
Triple<NodeRef, Boolean, NodeState> node = createOrFindNode(
target,
importableItem,
existingFileMode,
metadata);
boolean isDirectory = node.getSecond() == null ? false : node.getSecond(); // Watch out for NPEs during unboxing! boolean isDirectory = node.getSecond() == null ? false : node.getSecond(); // Watch out for NPEs during unboxing!
NodeState nodeState = node.getThird(); NodeState nodeState = node.getThird();
@@ -139,7 +149,7 @@ public class StreamingNodeImporterFactory extends AbstractNodeImporterFactory
} }
else else
{ {
numVersionProperties = importImportableItemFile(result, importableItem, metadata, nodeState); numVersionProperties = importImportableItemFile(result, importableItem, metadata, nodeState, existingFileMode);
} }
importStatus.incrementNodesWritten(importableItem, isDirectory, nodeState, metadata.getProperties().size() + 4, numVersionProperties); importStatus.incrementNodesWritten(importableItem, isDirectory, nodeState, metadata.getProperties().size() + 4, numVersionProperties);

View File

@@ -25,23 +25,12 @@
*/ */
package org.alfresco.repo.bulkimport.impl; package org.alfresco.repo.bulkimport.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.query.CannedQueryPageDetails; import org.alfresco.query.CannedQueryPageDetails;
import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingRequest;
import org.alfresco.query.PagingResults; import org.alfresco.query.PagingResults;
import org.alfresco.repo.bulkimport.BulkImportParameters;
import org.alfresco.repo.bulkimport.NodeImporter;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.action.ActionService;
@@ -53,6 +42,8 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.RuleService; import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionService; import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
@@ -62,6 +53,24 @@ import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/** /**
* @since 4.0 * @since 4.0
*/ */
@@ -159,6 +168,118 @@ public class AbstractBulkImportTests
return folders; return folders;
} }
protected void testCanVersionDocsWithoutSpecialInputFileNameExtension(
Function<String, NodeImporter> importerFun)
throws IOException, SystemException, NotSupportedException, HeuristicRollbackException,
HeuristicMixedException, RollbackException
{
txn = transactionService.getUserTransaction();
txn.begin();
NodeRef folderNode = topLevelFolder.getNodeRef();
// Import with appropriate importer.
// bulkimport-autoversion/{pass1,pass2,pass3}/example.txt contains different versions of the
// same file. Run the import once for each subfolder, the file will then get loaded
// creating a new version for each example.txt
NodeImporter nodeImporter = importerFun.apply("pass1");
BulkImportParameters bulkImportParameters = new BulkImportParameters();
bulkImportParameters.setTarget(folderNode);
bulkImportParameters.setExistingFileMode(BulkImportParameters.ExistingFileMode.ADD_VERSION);
bulkImportParameters.setBatchSize(1);
ExpectedFile[] expectedFiles = new ExpectedFile[]{
new ExpectedFile("example.txt", MimetypeMap.MIMETYPE_TEXT_PLAIN,
"This is an example file. This content is version 1.")
};
ExpectedFolder[] expectedFolders = new ExpectedFolder[] { };
// Import initial version
bulkImporter.bulkImport(bulkImportParameters, nodeImporter);
txn.commit();
txn = transactionService.getUserTransaction();
txn.begin();
assertEquals(false, bulkImporter.getStatus().inProgress());
checkFiles(folderNode, null, expectedFiles, expectedFolders);
Map<String, FileInfo> files = toMap(getFiles(folderNode, null));
NodeRef fileNodeRef = files.get("example.txt").getNodeRef();
assertFalse("Imported file should not yet be versioned:", versionService.isVersioned(fileNodeRef));
// Import revised document/version
nodeImporter = importerFun.apply("pass2");
bulkImporter.bulkImport(bulkImportParameters, nodeImporter);
txn.commit();
txn = transactionService.getUserTransaction();
txn.begin();
expectedFiles = new ExpectedFile[]{
new ExpectedFile("example.txt", MimetypeMap.MIMETYPE_TEXT_PLAIN,
// Note that pass2 has two versions 2 and 3 in it.
"This is an example file. This content is version 3.")
};
checkFiles(folderNode, null, expectedFiles, expectedFolders);
// Import revised document/version
nodeImporter = importerFun.apply("pass3");
bulkImporter.bulkImport(bulkImportParameters, nodeImporter);
txn.commit();
txn = transactionService.getUserTransaction();
txn.begin();
expectedFiles = new ExpectedFile[]{
new ExpectedFile("example.txt", MimetypeMap.MIMETYPE_TEXT_PLAIN,
"This is an example file. This content is version 4."),
};
expectedFolders = new ExpectedFolder[] {
new ExpectedFolder("banana")
};
checkFiles(folderNode, null, expectedFiles, expectedFolders);
// Check the files in the subfolder of pass3
NodeRef subFolder = fileFolderService.searchSimple(folderNode, "banana");
expectedFiles = new ExpectedFile[]{
new ExpectedFile("file.txt", MimetypeMap.MIMETYPE_TEXT_PLAIN,
"Version 2")
};
expectedFolders = new ExpectedFolder[] { };
checkFiles(subFolder, null, expectedFiles, expectedFolders);
assertTrue("Imported file should be versioned:", versionService.isVersioned(fileNodeRef));
VersionHistory history = versionService.getVersionHistory(fileNodeRef);
assertNotNull(history);
assertEquals("Incorrect number of versions.", 4, history.getAllVersions().size());
Version[] versions = history.getAllVersions().toArray(new Version[4]);
// Check the content of each version
ContentReader contentReader;
contentReader = contentService.getReader(versions[0].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT);
assertNotNull(contentReader);
assertEquals("4.0", versions[0].getVersionLabel());
assertEquals("This is an example file. This content is version 4.", contentReader.getContentString());
contentReader = contentService.getReader(versions[1].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT);
assertNotNull(contentReader);
assertEquals("3.0", versions[1].getVersionLabel());
assertEquals("This is an example file. This content is version 3.", contentReader.getContentString());
contentReader = contentService.getReader(versions[2].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT);
assertNotNull(contentReader);
assertEquals("2.0", versions[2].getVersionLabel());
assertEquals("This is an example file. This content is version 2.", contentReader.getContentString());
contentReader = contentService.getReader(versions[3].getFrozenStateNodeRef(), ContentModel.PROP_CONTENT);
assertNotNull(contentReader);
assertEquals("1.0", versions[3].getVersionLabel());
assertEquals("This is an example file. This content is version 1.", contentReader.getContentString());
}
protected List<FileInfo> getFiles(NodeRef parent, String pattern) protected List<FileInfo> getFiles(NodeRef parent, String pattern)
{ {
PagingResults<FileInfo> page = fileFolderService.list(parent, true, false, pattern, null, null, new PagingRequest(CannedQueryPageDetails.DEFAULT_PAGE_SIZE)); PagingResults<FileInfo> page = fileFolderService.list(parent, true, false, pattern, null, null, new PagingRequest(CannedQueryPageDetails.DEFAULT_PAGE_SIZE));
@@ -184,28 +305,41 @@ public class AbstractBulkImportTests
checkFiles(folder1, pattern, numExpectedFolders, numExpectedFiles, expectedFiles, expectedFolders); checkFiles(folder1, pattern, numExpectedFolders, numExpectedFiles, expectedFiles, expectedFolders);
} }
protected void checkFiles(NodeRef parent, String pattern,
ExpectedFile[] expectedFiles, ExpectedFolder[] expectedFolders)
{
int expectedFilesLength = expectedFiles != null ? expectedFiles.length : 0;
int expectedFoldersLength = expectedFolders != null ? expectedFolders.length : 0;
checkFiles(parent, pattern, expectedFoldersLength, expectedFilesLength, expectedFiles, expectedFolders);
}
protected void checkFiles(NodeRef parent, String pattern, int expectedNumFolders, int expectedNumFiles, protected void checkFiles(NodeRef parent, String pattern, int expectedNumFolders, int expectedNumFiles,
ExpectedFile[] expectedFiles, ExpectedFolder[] expectedFolders) ExpectedFile[] expectedFiles, ExpectedFolder[] expectedFolders)
{ {
Map<String, FileInfo> folders = toMap(getFolders(parent, pattern)); Map<String, FileInfo> folders = toMap(getFolders(parent, pattern));
Map<String, FileInfo> files = toMap(getFiles(parent, pattern)); Map<String, FileInfo> files = toMap(getFiles(parent, pattern));
assertEquals("", expectedNumFolders, folders.size()); assertEquals("Incorrect number of folders", expectedNumFolders, folders.size());
assertEquals("", expectedNumFiles, files.size()); assertEquals("Incorrect number of files", expectedNumFiles, files.size());
if(expectedFiles != null) if(expectedFiles != null)
{ {
for(ExpectedFile expectedFile : expectedFiles) for(ExpectedFile expectedFile : expectedFiles)
{ {
FileInfo fileInfo = files.get(expectedFile.getName()); FileInfo fileInfo = files.get(expectedFile.getName());
assertNotNull("", fileInfo); assertNotNull(
assertNotNull("", fileInfo.getContentData()); "Couldn't find expected file: "+expectedFile.getName()+
", found: "+files.keySet(), fileInfo);
assertNotNull("Content data unexpected null for "+expectedFile.getName(), fileInfo.getContentData());
assertEquals(expectedFile.getMimeType(), fileInfo.getContentData().getMimetype()); assertEquals(expectedFile.getMimeType(), fileInfo.getContentData().getMimetype());
if(fileInfo.getContentData().getMimetype() == MimetypeMap.MIMETYPE_TEXT_PLAIN if(fileInfo.getContentData().getMimetype().equals(MimetypeMap.MIMETYPE_TEXT_PLAIN)
&& expectedFile.getContentContains() != null) && expectedFile.getContentContains() != null)
{ {
ContentReader reader = contentService.getReader(fileInfo.getNodeRef(), ContentModel.PROP_CONTENT); ContentReader reader = contentService.getReader(fileInfo.getNodeRef(), ContentModel.PROP_CONTENT);
String contentContains = expectedFile.getContentContains(); String contentContains = expectedFile.getContentContains();
assertTrue("", reader.getContentString().indexOf(contentContains) != -1); String actualContent = reader.getContentString();
assertTrue("Expected contents doesn't include text: " + contentContains +
", full text:\n"+actualContent,
actualContent.contains(contentContains));
} }
} }
} }

View File

@@ -25,28 +25,6 @@
*/ */
package org.alfresco.repo.bulkimport.impl; package org.alfresco.repo.bulkimport.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.evaluator.NoConditionEvaluator; import org.alfresco.repo.action.evaluator.NoConditionEvaluator;
import org.alfresco.repo.action.executer.CopyActionExecuter; import org.alfresco.repo.action.executer.CopyActionExecuter;
@@ -70,6 +48,31 @@ import org.junit.Test;
import org.junit.experimental.categories.Category; import org.junit.experimental.categories.Category;
import org.springframework.util.ResourceUtils; import org.springframework.util.ResourceUtils;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/** /**
* @since 4.0 * @since 4.0
*/ */
@@ -666,6 +669,34 @@ public class BulkImportTest extends AbstractBulkImportTests
Files.deleteIfExists(dest); Files.deleteIfExists(dest);
} }
/**
* Simplifies calling {@ResourceUtils.getFile} so that a {@link RuntimeException}
* is thrown rather than a checked {@link FileNotFoundException} exception.
*
* @param resourceName e.g. "classpath:folder/file"
* @return File object
*/
private File resourceAsFile(String resourceName)
{
try
{
return ResourceUtils.getFile(resourceName);
}
catch (FileNotFoundException e)
{
throw new RuntimeException("Resource "+resourceName+" not found", e);
}
}
@Test
public void canVersionDocsWithoutSpecialInputFileNameExtension()
throws HeuristicMixedException, IOException, SystemException,
HeuristicRollbackException, NotSupportedException, RollbackException
{
testCanVersionDocsWithoutSpecialInputFileNameExtension(file ->
streamingNodeImporterFactory.getNodeImporter(resourceAsFile("classpath:bulkimport-autoversion/"+file)));
}
private void unpack(Path source, Path destFile) private void unpack(Path source, Path destFile)
{ {
Path archive = source.resolve("testbulk.gz"); Path archive = source.resolve("testbulk.gz");

View File

@@ -0,0 +1 @@
This is an example file. This content is version 1.

View File

@@ -0,0 +1 @@
This is an example file. This content is version 3.

View File

@@ -0,0 +1 @@
This is an example file. This content is version 2.

View File

@@ -0,0 +1 @@
This will be skipped as there is no another.txt in the repository.

View File

@@ -0,0 +1 @@
This is an example file. This content is version 4.

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="cm:title" />
<entry key="cm:name">banana</entry>
<entry key="cm:description">This is the banana folder</entry>
</properties>

View File

@@ -0,0 +1 @@
Version 2

View File

@@ -0,0 +1 @@
Version 1