SLING-8390 - Converter not handling serviceusers and acls spread across
multiple packages
ordering of packages
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncher.java b/src/main/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncher.java
index 29090c8..f0e811c 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncher.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncher.java
@@ -17,9 +17,20 @@
package org.apache.sling.feature.cpconverter.cli;
import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.TimeZone;
+import org.apache.jackrabbit.vault.packaging.CyclicDependencyException;
+import org.apache.jackrabbit.vault.packaging.Dependency;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.impl.ZipVaultPackage;
import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -114,7 +125,7 @@
}
}
- List<File> orderedContentPackages = order(contentPackages);
+ List<File> orderedContentPackages = order(contentPackages, logger);
for (File contentPackage : orderedContentPackages) {
converter.convert(contentPackage);
@@ -141,9 +152,51 @@
logger.info( "+-----------------------------------------------------+" );
}
- private List<File> order(List<File> contentPackages) {
- // TODO
- return null;
+ protected List<File> order(List<File> contentPackages, final Logger logger) throws CyclicDependencyException {
+
+ LinkedHashMap<PackageId, File> idFileMap = new LinkedHashMap<>();
+
+ Map<ZipVaultPackage, File> packageFileMapping = new HashMap<>();
+ Map<PackageId, ZipVaultPackage> idPackageMapping = new HashMap<>();
+
+ for (File file : contentPackages) {
+ try {
+ ZipVaultPackage pack = new ZipVaultPackage(file, false, true);
+ packageFileMapping.put(pack, file);
+ idPackageMapping.put(pack.getId(), pack);
+ } catch (IOException e) {
+ String msg = String.format("Package couldn't be parsed as ZipVaultPackage %s", file.getAbsolutePath());
+ logger.error(msg);
+ System.exit(1);
+ }
+ }
+
+
+ for (ZipVaultPackage pack : packageFileMapping.keySet()) {
+ orderDependencies(idFileMap, packageFileMapping, idPackageMapping, pack, new HashSet<PackageId>());
+ }
+
+ return new LinkedList<>(idFileMap.values());
+ }
+
+ private void orderDependencies(LinkedHashMap<PackageId, File> idFileMap,
+ Map<ZipVaultPackage, File> packageFileMapping, Map<PackageId, ZipVaultPackage> idPackageMapping,
+ ZipVaultPackage pack, Set<PackageId> visited) throws CyclicDependencyException {
+ if(visited.contains(pack.getId())) {
+ throw new CyclicDependencyException();
+ }
+ visited.add(pack.getId());
+ Dependency[] deps = pack.getDependencies();
+ for (Dependency dep : deps) {
+ for (PackageId id : new HashSet<>(idPackageMapping.keySet())) {
+ if (dep.matches(id)) {
+ orderDependencies(idFileMap, packageFileMapping, idPackageMapping, idPackageMapping.get(id), visited);
+ break;
+ }
+ }
+ }
+ idFileMap.put(pack.getId(), packageFileMapping.get(pack));
+ idPackageMapping.remove(pack.getId());
}
private static void printVersion(final Logger logger) {
diff --git a/src/test/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncherTest.java b/src/test/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncherTest.java
new file mode 100644
index 0000000..24f4696
--- /dev/null
+++ b/src/test/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncherTest.java
@@ -0,0 +1,61 @@
+package org.apache.sling.feature.cpconverter.cli;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.vault.packaging.CyclicDependencyException;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ContentPackage2FeatureModelConverterLauncherTest {
+
+ /**
+ * Test package A-1.0. Depends on B and C-1.X
+ * Test package B-1.0. Depends on C
+ */
+ private static String[] TEST_PACKAGES_INPUT = {"test_c-1.0.zip","test_a-1.0.zip","test_b-1.0.zip"};
+ private static String[] TEST_PACKAGES_OUTPUT = {"test_c-1.0.zip","test_b-1.0.zip","test_a-1.0.zip"};
+
+ private static String[] TEST_PACKAGES_CYCLIC_DEPENDENCY = {"test_d-1.0.zip","test_c-1.0.zip","test_a-1.0.zip","test_b-1.0.zip","test_e-1.0.zip"};
+
+
+ @Test
+ public void testPackageOrdering() throws CyclicDependencyException {
+ ContentPackage2FeatureModelConverterLauncher launcher = new ContentPackage2FeatureModelConverterLauncher();
+ Logger logger = LoggerFactory.getLogger("test");
+ List<File> contentPackages = new ArrayList<File>();
+
+ for (String pkgName : TEST_PACKAGES_INPUT) {
+ URL packageUrl = getClass().getResource(pkgName);
+ contentPackages.add(FileUtils.toFile(packageUrl));
+ }
+ List<File> ordered = launcher.order(contentPackages, logger);
+ Iterator<File> fileIt = ordered.iterator();
+ for (String expected : TEST_PACKAGES_OUTPUT) {
+ File next = fileIt.next();
+ assertEquals(expected, next.getName());
+ }
+
+ }
+
+ @Test(expected = CyclicDependencyException.class)
+ public void testDependencyCycle() throws CyclicDependencyException {
+ ContentPackage2FeatureModelConverterLauncher launcher = new ContentPackage2FeatureModelConverterLauncher();
+ Logger logger = LoggerFactory.getLogger("test");
+ List<File> contentPackages = new ArrayList<File>();
+
+ for (String pkgName : TEST_PACKAGES_CYCLIC_DEPENDENCY) {
+ URL packageUrl = getClass().getResource(pkgName);
+ contentPackages.add(FileUtils.toFile(packageUrl));
+ }
+ launcher.order(contentPackages, logger);
+ }
+
+}
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_a-1.0.zip b/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_a-1.0.zip
new file mode 100644
index 0000000..08df03a
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_a-1.0.zip
Binary files differ
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_b-1.0.zip b/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_b-1.0.zip
new file mode 100644
index 0000000..85fac13
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_b-1.0.zip
Binary files differ
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_c-1.0.zip b/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_c-1.0.zip
new file mode 100644
index 0000000..245291a
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_c-1.0.zip
Binary files differ
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_d-1.0.zip b/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_d-1.0.zip
new file mode 100644
index 0000000..7acf3d1
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_d-1.0.zip
Binary files differ
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_e-1.0.zip b/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_e-1.0.zip
new file mode 100644
index 0000000..372bbb9
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/cli/test_e-1.0.zip
Binary files differ