diff --git a/source/java/org/alfresco/repo/bulkimport/BulkImportParameters.java b/source/java/org/alfresco/repo/bulkimport/BulkImportParameters.java
index edd3388043..b79b3cbe01 100644
--- a/source/java/org/alfresco/repo/bulkimport/BulkImportParameters.java
+++ b/source/java/org/alfresco/repo/bulkimport/BulkImportParameters.java
@@ -1,36 +1,45 @@
-/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see .
- * #L%
- */
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
package org.alfresco.repo.bulkimport;
import org.alfresco.service.cmr.repository.NodeRef;
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 boolean replaceExisting = false;
private Integer batchSize;
private Integer numThreads;
private Integer loggingInterval;
@@ -60,14 +69,6 @@ public class BulkImportParameters
{
this.target = target;
}
- public boolean isReplaceExisting()
- {
- return replaceExisting;
- }
- public void setReplaceExisting(boolean replaceExisting)
- {
- this.replaceExisting = replaceExisting;
- }
public Integer getBatchSize()
{
return batchSize;
@@ -84,5 +85,40 @@ public class BulkImportParameters
{
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;
+ }
}
diff --git a/source/java/org/alfresco/repo/bulkimport/ImportableItem.java b/source/java/org/alfresco/repo/bulkimport/ImportableItem.java
index 2503950806..06e740f5dc 100644
--- a/source/java/org/alfresco/repo/bulkimport/ImportableItem.java
+++ b/source/java/org/alfresco/repo/bulkimport/ImportableItem.java
@@ -120,6 +120,10 @@ public final class ImportableItem
public Set getVersionEntries()
{
+ if (versionEntries == null)
+ {
+ return Collections.emptySet();
+ }
return(Collections.unmodifiableSet(versionEntries));
}
diff --git a/source/java/org/alfresco/repo/bulkimport/NodeImporter.java b/source/java/org/alfresco/repo/bulkimport/NodeImporter.java
index f299accd54..288a5fc5ef 100644
--- a/source/java/org/alfresco/repo/bulkimport/NodeImporter.java
+++ b/source/java/org/alfresco/repo/bulkimport/NodeImporter.java
@@ -23,20 +23,20 @@
* along with Alfresco. If not, see .
* #L%
*/
-package org.alfresco.repo.bulkimport;
-
-import java.io.File;
-
-import org.alfresco.service.cmr.repository.NodeRef;
-
-/**
- * Imports an importable item in the filesystem into the repository by creating a node to represent it.
- *
- * @since 4.0
- *
- */
-public interface NodeImporter
-{
- public NodeRef importImportableItem(ImportableItem importableItem, boolean replaceExisting);
- public File getSourceFolder();
-}
+package org.alfresco.repo.bulkimport;
+
+import java.io.File;
+
+import org.alfresco.service.cmr.repository.NodeRef;
+
+/**
+ * Imports an importable item in the filesystem into the repository by creating a node to represent it.
+ *
+ * @since 4.0
+ *
+ */
+public interface NodeImporter
+{
+ public NodeRef importImportableItem(ImportableItem importableItem, BulkImportParameters.ExistingFileMode existingFileMode);
+ public File getSourceFolder();
+}
diff --git a/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java b/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java
index 8ad21457f8..256438b356 100644
--- a/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java
+++ b/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java
@@ -1,20 +1,20 @@
/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
@@ -33,6 +33,7 @@ import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.bulkimport.BulkFilesystemImporter;
+import org.alfresco.repo.bulkimport.BulkImportParameters;
import org.alfresco.repo.bulkimport.DirectoryAnalyser;
import org.alfresco.repo.bulkimport.ImportableItem;
import org.alfresco.repo.bulkimport.MetadataLoader;
@@ -99,7 +100,7 @@ public abstract class AbstractNodeImporter implements NodeImporter
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);
/*
@@ -181,11 +182,19 @@ public abstract class AbstractNodeImporter implements NodeImporter
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;
- 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 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);
}
@@ -242,9 +251,18 @@ public abstract class AbstractNodeImporter implements NodeImporter
return(result);
}
- protected final Triple createOrFindNode(NodeRef target, ImportableItem importableItem,
- boolean replaceExisting, MetadataLoader.Metadata metadata)
+ // TODO: this is a confusing method that does too many things. It doesn't just "create or find"
+ // 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 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 result = null;
boolean isDirectory = false;
NodeState nodeState = replaceExisting ? NodeState.REPLACED : NodeState.SKIPPED;
@@ -424,14 +442,14 @@ public abstract class AbstractNodeImporter implements NodeImporter
return(result);
}
- public NodeRef importImportableItem(ImportableItem importableItem, boolean replaceExisting)
+ public NodeRef importImportableItem(ImportableItem importableItem, BulkImportParameters.ExistingFileMode existingFileMode)
{
if(logger.isDebugEnabled())
{
logger.debug("Importing " + String.valueOf(importableItem));
}
- NodeRef nodeRef = importImportableItemImpl(importableItem, replaceExisting);
+ NodeRef nodeRef = importImportableItemImpl(importableItem, existingFileMode);
// allow parent to be garbage collected
//importableItem.setParent(null);
diff --git a/source/java/org/alfresco/repo/bulkimport/impl/BulkImportStatusImpl.java b/source/java/org/alfresco/repo/bulkimport/impl/BulkImportStatusImpl.java
index 1514bd65b3..ea4828dc45 100644
--- a/source/java/org/alfresco/repo/bulkimport/impl/BulkImportStatusImpl.java
+++ b/source/java/org/alfresco/repo/bulkimport/impl/BulkImportStatusImpl.java
@@ -1,28 +1,28 @@
-/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see .
- * #L%
- */
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
package org.alfresco.repo.bulkimport.impl;
import java.io.PrintWriter;
diff --git a/source/java/org/alfresco/repo/bulkimport/impl/MultiThreadedBulkFilesystemImporter.java b/source/java/org/alfresco/repo/bulkimport/impl/MultiThreadedBulkFilesystemImporter.java
index b95a5b2cfd..5619f881c6 100644
--- a/source/java/org/alfresco/repo/bulkimport/impl/MultiThreadedBulkFilesystemImporter.java
+++ b/source/java/org/alfresco/repo/bulkimport/impl/MultiThreadedBulkFilesystemImporter.java
@@ -1,28 +1,28 @@
-/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see .
- * #L%
- */
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
package org.alfresco.repo.bulkimport.impl;
import org.alfresco.model.ContentModel;
@@ -126,7 +126,7 @@ public abstract class MultiThreadedBulkFilesystemImporter extends AbstractBulkFi
{
behaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
- NodeRef nodeRef = nodeImporter.importImportableItem(importableItem, bulkImportParameters.isReplaceExisting());
+ NodeRef nodeRef = nodeImporter.importImportableItem(importableItem, bulkImportParameters.getExistingFileMode());
filesystemTracker.itemImported(nodeRef, importableItem);
}
finally
diff --git a/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java b/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java
index 49ca7173d6..705a8e6633 100644
--- a/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java
+++ b/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java
@@ -1,20 +1,20 @@
/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
@@ -30,6 +30,7 @@ import java.io.IOException;
import java.nio.file.Files;
import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.repo.bulkimport.BulkImportParameters;
import org.alfresco.repo.bulkimport.ImportableItem;
import org.alfresco.repo.bulkimport.MetadataLoader;
import org.alfresco.repo.bulkimport.NodeImporter;
@@ -109,7 +110,7 @@ public class StreamingNodeImporterFactory extends AbstractNodeImporterFactory
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();
if(target == null)
@@ -120,7 +121,16 @@ public class StreamingNodeImporterFactory extends AbstractNodeImporterFactory
NodeRef result = null;
MetadataLoader.Metadata metadata = loadMetadata(importableItem.getHeadRevision());
- Triple 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 node = createOrFindNode(
+ target,
+ importableItem,
+ existingFileMode,
+ metadata);
boolean isDirectory = node.getSecond() == null ? false : node.getSecond(); // Watch out for NPEs during unboxing!
NodeState nodeState = node.getThird();
@@ -139,7 +149,7 @@ public class StreamingNodeImporterFactory extends AbstractNodeImporterFactory
}
else
{
- numVersionProperties = importImportableItemFile(result, importableItem, metadata, nodeState);
+ numVersionProperties = importImportableItemFile(result, importableItem, metadata, nodeState, existingFileMode);
}
importStatus.incrementNodesWritten(importableItem, isDirectory, nodeState, metadata.getProperties().size() + 4, numVersionProperties);
diff --git a/source/test-java/org/alfresco/repo/bulkimport/impl/AbstractBulkImportTests.java b/source/test-java/org/alfresco/repo/bulkimport/impl/AbstractBulkImportTests.java
index 12b0109b38..7bb311c07a 100644
--- a/source/test-java/org/alfresco/repo/bulkimport/impl/AbstractBulkImportTests.java
+++ b/source/test-java/org/alfresco/repo/bulkimport/impl/AbstractBulkImportTests.java
@@ -1,47 +1,36 @@
-/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see .
- * #L%
- */
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
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.query.CannedQueryPageDetails;
import org.alfresco.query.PagingRequest;
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.security.authentication.AuthenticationUtil;
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.StoreRef;
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.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
@@ -62,6 +53,24 @@ import org.junit.AfterClass;
import org.junit.Before;
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
*/
@@ -159,6 +168,118 @@ public class AbstractBulkImportTests
return folders;
}
+ protected void testCanVersionDocsWithoutSpecialInputFileNameExtension(
+ Function 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 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 getFiles(NodeRef parent, String pattern)
{
PagingResults 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);
}
+ 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,
ExpectedFile[] expectedFiles, ExpectedFolder[] expectedFolders)
{
Map folders = toMap(getFolders(parent, pattern));
Map files = toMap(getFiles(parent, pattern));
- assertEquals("", expectedNumFolders, folders.size());
- assertEquals("", expectedNumFiles, files.size());
+ assertEquals("Incorrect number of folders", expectedNumFolders, folders.size());
+ assertEquals("Incorrect number of files", expectedNumFiles, files.size());
if(expectedFiles != null)
{
for(ExpectedFile expectedFile : expectedFiles)
{
FileInfo fileInfo = files.get(expectedFile.getName());
- assertNotNull("", fileInfo);
- assertNotNull("", fileInfo.getContentData());
+ assertNotNull(
+ "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());
- if(fileInfo.getContentData().getMimetype() == MimetypeMap.MIMETYPE_TEXT_PLAIN
+ if(fileInfo.getContentData().getMimetype().equals(MimetypeMap.MIMETYPE_TEXT_PLAIN)
&& expectedFile.getContentContains() != null)
{
ContentReader reader = contentService.getReader(fileInfo.getNodeRef(), ContentModel.PROP_CONTENT);
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));
}
}
}
diff --git a/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java b/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java
index 302cc2eac3..c9f72a337d 100644
--- a/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java
+++ b/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java
@@ -1,20 +1,20 @@
/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
@@ -25,28 +25,6 @@
*/
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.repo.action.evaluator.NoConditionEvaluator;
import org.alfresco.repo.action.executer.CopyActionExecuter;
@@ -70,6 +48,31 @@ import org.junit.Test;
import org.junit.experimental.categories.Category;
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
*/
@@ -272,7 +275,7 @@ public class BulkImportTest extends AbstractBulkImportTests
System.out.println(bulkImporter.getStatus());
- assertEquals(74, bulkImporter.getStatus().getNumberOfContentNodesCreated());
+ assertEquals(74, bulkImporter.getStatus().getNumberOfContentNodesCreated());
checkFiles(folderNode, null, 2, 9, new ExpectedFile[] {
new ExpectedFile("quickImg1.xls", MimetypeMap.MIMETYPE_EXCEL),
@@ -628,9 +631,9 @@ public class BulkImportTest extends AbstractBulkImportTests
NodeImporter nodeImporter = null;
File source = ResourceUtils.getFile("classpath:bulkimport4");
- //Simulate the name of the file with an invalid encoding.
- String fileName = new String("135 CarbonÔÇô13 NMR spectroscopy_DS_NS_final_cau.txt".getBytes(Charset.forName("ISO-8859-1")),
- Charset.forName("UTF-8"));
+ //Simulate the name of the file with an invalid encoding.
+ String fileName = new String("135 CarbonÔÇô13 NMR spectroscopy_DS_NS_final_cau.txt".getBytes(Charset.forName("ISO-8859-1")),
+ Charset.forName("UTF-8"));
Path dest = source.toPath().resolve("encoding");
try
{
@@ -638,7 +641,7 @@ public class BulkImportTest extends AbstractBulkImportTests
}
catch (FileAlreadyExistsException ex)
{
- //It is fine if the folder already exists, though it should not.
+ //It is fine if the folder already exists, though it should not.
}
Path destFile = dest.resolve(fileName);
@@ -656,7 +659,7 @@ public class BulkImportTest extends AbstractBulkImportTests
bulkImportParameters.setBatchSize(40);
bulkImporter.bulkImport(bulkImportParameters, nodeImporter);
- assertEquals(1, bulkImporter.getStatus().getNumberOfContentNodesCreated());
+ assertEquals(1, bulkImporter.getStatus().getNumberOfContentNodesCreated());
checkFiles(folderNode, null, 0, 1,
new ExpectedFile[] { new ExpectedFile(fileName, MimetypeMap.MIMETYPE_TEXT_PLAIN)},
@@ -665,7 +668,35 @@ public class BulkImportTest extends AbstractBulkImportTests
Files.deleteIfExists(destFile);
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)
{
Path archive = source.resolve("testbulk.gz");
diff --git a/source/test-resources/bulkimport-autoversion/pass1/example.txt b/source/test-resources/bulkimport-autoversion/pass1/example.txt
new file mode 100644
index 0000000000..609550b9fd
--- /dev/null
+++ b/source/test-resources/bulkimport-autoversion/pass1/example.txt
@@ -0,0 +1 @@
+This is an example file. This content is version 1.
\ No newline at end of file
diff --git a/source/test-resources/bulkimport-autoversion/pass2/example.txt b/source/test-resources/bulkimport-autoversion/pass2/example.txt
new file mode 100644
index 0000000000..6f55b208c7
--- /dev/null
+++ b/source/test-resources/bulkimport-autoversion/pass2/example.txt
@@ -0,0 +1 @@
+This is an example file. This content is version 3.
\ No newline at end of file
diff --git a/source/test-resources/bulkimport-autoversion/pass2/example.txt.v123 b/source/test-resources/bulkimport-autoversion/pass2/example.txt.v123
new file mode 100644
index 0000000000..b5aaf5e7fd
--- /dev/null
+++ b/source/test-resources/bulkimport-autoversion/pass2/example.txt.v123
@@ -0,0 +1 @@
+This is an example file. This content is version 2.
\ No newline at end of file
diff --git a/source/test-resources/bulkimport-autoversion/pass3/another.txt.v1 b/source/test-resources/bulkimport-autoversion/pass3/another.txt.v1
new file mode 100644
index 0000000000..fa8212f996
--- /dev/null
+++ b/source/test-resources/bulkimport-autoversion/pass3/another.txt.v1
@@ -0,0 +1 @@
+This will be skipped as there is no another.txt in the repository.
\ No newline at end of file
diff --git a/source/test-resources/bulkimport-autoversion/pass3/example.txt b/source/test-resources/bulkimport-autoversion/pass3/example.txt
new file mode 100644
index 0000000000..e31352904d
--- /dev/null
+++ b/source/test-resources/bulkimport-autoversion/pass3/example.txt
@@ -0,0 +1 @@
+This is an example file. This content is version 4.
\ No newline at end of file
diff --git a/source/test-resources/bulkimport-autoversion/pass3/subfolder.metadata.properties.xml b/source/test-resources/bulkimport-autoversion/pass3/subfolder.metadata.properties.xml
new file mode 100644
index 0000000000..fdabbce432
--- /dev/null
+++ b/source/test-resources/bulkimport-autoversion/pass3/subfolder.metadata.properties.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+ banana
+ This is the banana folder
+
diff --git a/source/test-resources/bulkimport-autoversion/pass3/subfolder/file.txt b/source/test-resources/bulkimport-autoversion/pass3/subfolder/file.txt
new file mode 100644
index 0000000000..ff55721fa3
--- /dev/null
+++ b/source/test-resources/bulkimport-autoversion/pass3/subfolder/file.txt
@@ -0,0 +1 @@
+Version 2
\ No newline at end of file
diff --git a/source/test-resources/bulkimport-autoversion/pass3/subfolder/file.txt.v1 b/source/test-resources/bulkimport-autoversion/pass3/subfolder/file.txt.v1
new file mode 100644
index 0000000000..ada091bb9c
--- /dev/null
+++ b/source/test-resources/bulkimport-autoversion/pass3/subfolder/file.txt.v1
@@ -0,0 +1 @@
+Version 1
\ No newline at end of file