[KARAF-6431] - Maven plugin feature to define custom bundle location prefixes (#882)

[KARAF-6431] - Maven plugin feature to define custom bundle location prefixes
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/download/impl/DownloadManagerHelper.java b/features/core/src/main/java/org/apache/karaf/features/internal/download/impl/DownloadManagerHelper.java
index ba2ffed..a3951ec 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/download/impl/DownloadManagerHelper.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/download/impl/DownloadManagerHelper.java
@@ -16,17 +16,41 @@
  */
 package org.apache.karaf.features.internal.download.impl;
 
+import java.util.Collection;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 public final class DownloadManagerHelper {
 
-    private static final Pattern IGNORED_PROTOCOL_PATTERN = Pattern.compile("^(jar|war|war-i|warref|webbundle|wrap|spring|blueprint):.*$");
+    private static final String DEFAULT_IGNORED_PROTOCOL_PATTERN = "jar|war|war-i|warref|webbundle|wrap|spring|blueprint";
+    private static Pattern ignoredProtocolPattern;
+
+    static {
+        setIgnoredProtocolPattern(DEFAULT_IGNORED_PROTOCOL_PATTERN);
+    }
 
     private DownloadManagerHelper() {
         //Utility Class
     }
 
+    public static Pattern getIgnoredProtocolPattern(){
+        return ignoredProtocolPattern;
+    }
+
+    private static void setIgnoredProtocolPattern(String pattern){
+        String defaultPattRegex = "^(" + pattern + "):.*$";
+        ignoredProtocolPattern = Pattern.compile(defaultPattRegex);
+    }
+
+    public static void setExtraProtocols( Collection<String> protocols ){
+        StringBuilder sb = new StringBuilder( DEFAULT_IGNORED_PROTOCOL_PATTERN );
+        for (String proto : protocols) {
+            sb.append( "|" + proto );
+        }
+
+        setIgnoredProtocolPattern(sb.toString());
+    }
+
     /**
      * Strips download urls from wrapper protocols.
      *
@@ -35,11 +59,11 @@
      */
     public static String stripUrl(String url) {
         String strippedUrl = url;
-        Matcher matcher = IGNORED_PROTOCOL_PATTERN.matcher(strippedUrl);
+        Matcher matcher = ignoredProtocolPattern.matcher(strippedUrl);
         while (matcher.matches()) {
             String protocol = matcher.group(1);
             strippedUrl = strippedUrl.substring(protocol.length() + 1);
-            matcher = IGNORED_PROTOCOL_PATTERN.matcher(strippedUrl);
+            matcher = ignoredProtocolPattern.matcher(strippedUrl);
         }
         if (strippedUrl.contains("?")) {
             strippedUrl = strippedUrl.substring(0, strippedUrl.indexOf('?'));
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/download/impl/DownloadManagerHelperTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/download/impl/DownloadManagerHelperTest.java
new file mode 100644
index 0000000..6753276
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/download/impl/DownloadManagerHelperTest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.features.internal.download.impl;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import static junit.framework.TestCase.assertEquals;
+
+public class DownloadManagerHelperTest {
+
+  @Test
+  public void testSetExtraProtocols(){
+    assertEquals("^(jar|war|war-i|warref|webbundle|wrap|spring|blueprint):.*$", DownloadManagerHelper.getIgnoredProtocolPattern().toString());
+
+    List<String> extraProtocols = new ArrayList<>();
+    extraProtocols.add( "extra1" );
+    extraProtocols.add( "extra2" );
+    DownloadManagerHelper.setExtraProtocols( extraProtocols );
+
+    assertEquals("^(jar|war|war-i|warref|webbundle|wrap|spring|blueprint|extra1|extra2):.*$", DownloadManagerHelper.getIgnoredProtocolPattern().toString());
+  }
+}
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
index 7dd741b..d667f16 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
@@ -73,6 +73,7 @@
 import org.apache.karaf.features.internal.download.DownloadManager;
 import org.apache.karaf.features.internal.download.Downloader;
 import org.apache.karaf.features.internal.download.StreamProvider;
+import org.apache.karaf.features.internal.download.impl.DownloadManagerHelper;
 import org.apache.karaf.features.internal.model.Bundle;
 import org.apache.karaf.features.internal.model.Conditional;
 import org.apache.karaf.features.internal.model.ConfigFile;
@@ -747,6 +748,13 @@
         return this;
     }
 
+
+    public Builder extraProtocols(Collection<String> protocols) {
+        DownloadManagerHelper.setExtraProtocols(protocols);
+        return this;
+    }
+
+
     /**
      * Configure a list of blacklisted features XML repository URIs (see {@link LocationPattern})
      * @param repositories
@@ -1659,6 +1667,7 @@
             }
             LOGGER.info("   Feature {} is defined as an installed feature", feature.getId());
             for (Bundle bundle : feature.getBundle()) {
+
                 if (!ignoreDependencyFlag || !bundle.isDependency()) {
                     installer.installArtifact(bundle);
                 }
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java
index dd87e25..83ce28b 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java
@@ -162,6 +162,12 @@
     protected int defaultStartLevel = 30;
 
     /**
+     * List of additional allowed protocols on bundles location URI
+     */
+    @Parameter
+    private List<String> extraProtocols;
+
+    /**
      * List of compile-scope features XML files to be used in startup stage (etc/startup.properties)
      */
     @Parameter
@@ -474,6 +480,7 @@
         Builder builder = Builder.newInstance();
 
         // Set up miscellaneous options
+        builder.extraProtocols(extraProtocols);
         builder.offline(mavenSession.isOffline());
         builder.localRepository(localRepo.getBasedir());
         builder.resolverWrapper((resolver) -> new ReactorMavenResolver(reactor, resolver));
@@ -814,6 +821,7 @@
         bootRepositories = nonNullList(bootRepositories);
         installedRepositories = nonNullList(installedRepositories);
         blacklistedRepositories = nonNullList(blacklistedRepositories);
+        extraProtocols = nonNullList(extraProtocols);
         startupBundles = nonNullList(startupBundles);
         bootBundles = nonNullList(bootBundles);
         installedBundles = nonNullList(installedBundles);