Merge pull request #9 from apache/feature/SLING-8567-respect-start-level

SLING-8567 respect start levels from JCR path and translate to feature
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/features/DefaultFeaturesManager.java b/src/main/java/org/apache/sling/feature/cpconverter/features/DefaultFeaturesManager.java
index f805eef..1a16252 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/features/DefaultFeaturesManager.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/features/DefaultFeaturesManager.java
@@ -110,6 +110,10 @@
     }
 
     public void addArtifact(String runMode, ArtifactId id) {
+        addArtifact(runMode, id, null);
+    }
+
+    public void addArtifact(String runMode, ArtifactId id, Integer startOrder) {
         requireNonNull(id, "Artifact can not be attached to a feature without specifying a valid ArtifactId.");
 
         Artifact artifact = new Artifact(id);
@@ -128,7 +132,8 @@
 
             artifacts = extension.getArtifacts();
         } else {
-            artifact.setStartOrder(bundlesStartOrder);
+            int startOrderForBundle = startOrder != null ? startOrder.intValue() : bundlesStartOrder;
+            artifact.setStartOrder(startOrderForBundle);
             artifacts = targetFeature.getBundles();
         }
 
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/features/FeaturesManager.java b/src/main/java/org/apache/sling/feature/cpconverter/features/FeaturesManager.java
index 30851be..9319d26 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/features/FeaturesManager.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/features/FeaturesManager.java
@@ -31,6 +31,8 @@
 
     void addArtifact(String runMode, ArtifactId id);
 
+    void addArtifact(String runMode, ArtifactId id, Integer startOrder);
+
     void addConfiguration(String runMode, String pid, Dictionary<String, Object> configurationProperties);
 
     void serialize() throws Exception;
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandler.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandler.java
index e757de0..c5eee53 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandler.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandler.java
@@ -33,6 +33,7 @@
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
 import org.apache.sling.feature.cpconverter.artifacts.InputStreamArtifactWriter;
+import org.codehaus.plexus.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -57,7 +58,7 @@
     private final Pattern pomPropertiesPattern = Pattern.compile("META-INF/maven/[^/]+/[^/]+/pom.properties");
 
     public BundleEntryHandler() {
-        super("/jcr_root/(?:apps|libs)/.+/install(\\.([^/]+))?/.+\\.jar");
+        super("/jcr_root/(?:apps|libs)/.+/install(?:\\.([^/]+))?/(?:([0-9]+)/)?.+\\.jar");
     }
 
     @Override
@@ -87,11 +88,9 @@
 
         Matcher matcher = getPattern().matcher(path);
         String runMode = null;
+        Integer startLevel = null;
         // we are pretty sure it matches, here
-        if (matcher.matches()) {
-            // there is a specified RunMode
-            runMode = matcher.group(2);
-        } else {
+        if (!matcher.matches()) {
             throw new IllegalStateException("Something went terribly wrong: pattern '"
                                             + getPattern().pattern()
                                             + "' should have matched already with path '"
@@ -99,12 +98,24 @@
                                             + "' but it does not, currently");
         }
 
+        if (StringUtils.isNotBlank(matcher.group(1))) {
+            // there is a specified RunMode
+            runMode = matcher.group(1);
+            logger.debug("Runmode {} was extracted from path {}", runMode, path);
+        }
+
+        if (StringUtils.isNotBlank(matcher.group(2))) {
+            // there is a specified Start Level
+            startLevel = Integer.parseInt(matcher.group(2)); // NumberFormatException impossible due to RegEx
+            logger.debug("Start level {} was extracted from path {}", startLevel, path);
+        }
+
         try (InputStream input = archive.openInputStream(entry)) {
             ArtifactId id = new ArtifactId(groupId, artifactId, version, classifier, JAR_TYPE);
 
             converter.getArtifactsDeployer().deploy(new InputStreamArtifactWriter(input), id);
 
-            converter.getFeaturesManager().addArtifact(runMode, id);
+            converter.getFeaturesManager().addArtifact(runMode, id, startLevel);
         }
     }
 
diff --git a/src/test/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandlerTest.java b/src/test/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandlerTest.java
index 23c9edf..ae2031d 100644
--- a/src/test/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandlerTest.java
+++ b/src/test/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandlerTest.java
@@ -53,9 +53,12 @@
 
     private final EntryHandler bundleEntryHandler;
 
-    public BundleEntryHandlerTest(String bundleLocation, EntryHandler bundleEntryHandler) {
+    private final int startOrder;
+
+    public BundleEntryHandlerTest(String bundleLocation, EntryHandler bundleEntryHandler, int startOrder) {
         this.bundleLocation = bundleLocation;
         this.bundleEntryHandler = bundleEntryHandler;
+        this.startOrder = startOrder;
     }
 
     @Test
@@ -108,6 +111,7 @@
         assertFalse(featuresManager.getTargetFeature().getBundles().isEmpty());
         assertEquals(1, feature.getBundles().size());
         assertEquals("org.apache.felix:org.apache.felix.framework:6.0.1", feature.getBundles().get(0).getId().toMvnId());
+        assertEquals(startOrder, feature.getBundles().get(0).getStartOrder());
     }
 
     @Parameters
@@ -115,10 +119,12 @@
         final BundleEntryHandler bundleEntryHandler = new BundleEntryHandler();
 
         return Arrays.asList(new Object[][] {
-            { "/jcr_root/apps/asd/install/test-framework-no-pom.jar", bundleEntryHandler },
-            { "/jcr_root/apps/asd/install/test-framework.jar", bundleEntryHandler },
-            { "/jcr_root/apps/asd/install.author/test-framework.jar", bundleEntryHandler },
-            { "/jcr_root/apps/asd/install.publish/test-framework.jar", bundleEntryHandler }
+                { "/jcr_root/apps/asd/install/test-framework-no-pom.jar", bundleEntryHandler, 20 },
+                { "/jcr_root/apps/asd/install/test-framework.jar", bundleEntryHandler, 20 },
+                { "/jcr_root/apps/asd/install/9/test-framework.jar", bundleEntryHandler, 9 },
+                { "/jcr_root/apps/asd/install.author/test-framework.jar", bundleEntryHandler, 20 },
+                { "/jcr_root/apps/asd/install.author/9/test-framework.jar", bundleEntryHandler, 9 },
+                { "/jcr_root/apps/asd/install.publish/test-framework.jar", bundleEntryHandler, 20 }
         });
     }
 
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/apps/asd/install.author/9/test-framework.jar b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/apps/asd/install.author/9/test-framework.jar
new file mode 100644
index 0000000..9ce022d
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/apps/asd/install.author/9/test-framework.jar
Binary files differ
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/apps/asd/install/9/test-framework.jar b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/apps/asd/install/9/test-framework.jar
new file mode 100644
index 0000000..9ce022d
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/apps/asd/install/9/test-framework.jar
Binary files differ