This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/karaf.git


The following commit(s) were added to refs/heads/main by this push:
     new 5e4167f6ee fix(karaf-maven-plugin): Deal with non-features classifier 
in the karaf-maven-plugin (#2521)
5e4167f6ee is described below

commit 5e4167f6ee4b3902f9d7f97ae96089516d02aab3
Author: JB Onofré <[email protected]>
AuthorDate: Wed Apr 15 23:49:40 2026 +0200

    fix(karaf-maven-plugin): Deal with non-features classifier in the 
karaf-maven-plugin (#2521)
---
 .../tooling/features/GenerateDescriptorMojo.java   | 32 +++++++++++++++++-----
 .../karaf/tooling/utils/Dependency31Helper.java    | 32 +++++++++++++++++++++-
 2 files changed, 56 insertions(+), 8 deletions(-)

diff --git 
a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java
 
b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java
index 684c2527e9..0f8c386205 100644
--- 
a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java
+++ 
b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java
@@ -26,9 +26,11 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
 
@@ -37,6 +39,7 @@ import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.stream.XMLStreamException;
 
 import org.apache.karaf.features.internal.model.*;
+import org.apache.karaf.tooling.utils.Dependency31Helper;
 import org.apache.karaf.tooling.utils.DependencyHelper;
 import org.apache.karaf.tooling.utils.DependencyHelperFactory;
 import org.apache.karaf.tooling.utils.LocalDependency;
@@ -490,6 +493,7 @@ public class GenerateDescriptorMojo extends MojoSupport {
         // TODO Initialise the repositories from the existing feature file if 
any
         Map<Dependency, Feature> otherFeatures = new HashMap<>();
         Map<Feature, String> featureRepositories = new HashMap<>();
+        Set<Object> recognizedFeatures = new HashSet<>();
         FeaturesCache cache = new FeaturesCache(featuresCacheSize, 
artifactCacheSize);
         for (final LocalDependency entry : localDependencies) {
             Object artifact = entry.getArtifact();
@@ -499,7 +503,7 @@ public class GenerateDescriptorMojo extends MojoSupport {
             }
 
             processFeatureArtifact(features, feature, otherFeatures, 
featureRepositories, cache, artifact,
-                    entry.getParent(), true);
+                    entry.getParent(), true, recognizedFeatures);
         }
         // Do not retain cache beyond this point
         cache = null;
@@ -514,7 +518,7 @@ public class GenerateDescriptorMojo extends MojoSupport {
                     continue;
                 }
 
-                if (!this.dependencyHelper.isArtifactAFeature(artifact)) {
+                if (!this.dependencyHelper.isArtifactAFeature(artifact) && 
!recognizedFeatures.contains(artifact)) {
                     String bundleName = 
this.dependencyHelper.artifactToMvn(artifact, 
getVersionOrRange(entry.getParent(), artifact));
 
                     for (ConfigFile cf : feature.getConfigfile()) {
@@ -609,11 +613,25 @@ public class GenerateDescriptorMojo extends MojoSupport {
 
     private void processFeatureArtifact(Features features, Feature feature, 
Map<Dependency, Feature> otherFeatures,
                                         Map<Feature, String> 
featureRepositories, FeaturesCache cache,
-                                        Object artifact, Object parent, 
boolean add)
+                                        Object artifact, Object parent, 
boolean add, Set<Object> recognizedFeatures)
             throws MojoExecutionException, XMLStreamException, JAXBException, 
IOException {
-        if (this.dependencyHelper.isArtifactAFeature(artifact) && 
FEATURE_CLASSIFIER.equals(
-                this.dependencyHelper.getClassifier(artifact))) {
-            File featuresFile = this.dependencyHelper.resolve(artifact, 
getLog());
+        boolean isFeature = this.dependencyHelper.isArtifactAFeature(artifact);
+        File featuresFile = null;
+        if (!isFeature) {
+            // For XML artifacts with non-standard classifiers, resolve and 
check content
+            featuresFile = this.dependencyHelper.resolve(artifact, getLog());
+            if (featuresFile != null && featuresFile.exists()
+                    && Dependency31Helper.isFeaturesXml(featuresFile)) {
+                isFeature = true;
+            }
+        }
+        if (isFeature) {
+            if (recognizedFeatures != null) {
+                recognizedFeatures.add(artifact);
+            }
+            if (featuresFile == null) {
+                featuresFile = this.dependencyHelper.resolve(artifact, 
getLog());
+            }
             if (featuresFile == null || !featuresFile.exists()) {
                 throw new MojoExecutionException(
                         "Cannot locate file for feature: " + artifact + " at " 
+ featuresFile);
@@ -621,7 +639,7 @@ public class GenerateDescriptorMojo extends MojoSupport {
             Features includedFeatures = cache.getFeature(featuresFile);
             for (String repository : includedFeatures.getRepository()) {
                 processFeatureArtifact(features, feature, otherFeatures, 
featureRepositories, cache,
-                        cache.getArtifact(repository), parent, false);
+                        cache.getArtifact(repository), parent, false, 
recognizedFeatures);
             }
             for (Feature includedFeature : includedFeatures.getFeature()) {
                 Dependency dependency = new 
Dependency(includedFeature.getName(), includedFeature.getVersion());
diff --git 
a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/Dependency31Helper.java
 
b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/Dependency31Helper.java
index 44bd3d0fa2..497a8e7465 100644
--- 
a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/Dependency31Helper.java
+++ 
b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/Dependency31Helper.java
@@ -43,10 +43,16 @@ import org.eclipse.aether.util.graph.transformer.*;
 import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.*;
 
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+
 import static java.lang.String.*;
 import static org.apache.commons.lang3.reflect.MethodUtils.invokeMethod;
 import static 
org.apache.karaf.deployer.kar.KarArtifactInstaller.FEATURE_CLASSIFIER;
@@ -284,7 +290,31 @@ public class Dependency31Helper implements 
DependencyHelper {
     }
 
     public static boolean isFeature(Artifact artifact) {
-        return artifact.getExtension().equals("kar") || 
FEATURE_CLASSIFIER.equals(artifact.getClassifier());
+        if (artifact.getExtension().equals("kar") || 
FEATURE_CLASSIFIER.equals(artifact.getClassifier())) {
+            return true;
+        }
+        // For XML artifacts with non-standard classifiers, check actual 
content when the file is available
+        if ("xml".equals(artifact.getExtension()) && artifact.getFile() != 
null && artifact.getFile().exists()) {
+            return isFeaturesXml(artifact.getFile());
+        }
+        return false;
+    }
+
+    public static boolean isFeaturesXml(File file) {
+        try (InputStream is = new FileInputStream(file)) {
+            XMLInputFactory xif = XMLInputFactory.newFactory();
+            xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+            xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
+            xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, 
false);
+            XMLStreamReader r = xif.createXMLStreamReader(is);
+            r.nextTag();
+            QName name = r.getName();
+            return name.getLocalPart().equals("features")
+                    && (name.getNamespaceURI().isEmpty()
+                            || 
name.getNamespaceURI().startsWith("http://karaf.apache.org/xmlns/features/";));
+        } catch (Exception e) {
+            return false;
+        }
     }
 
     @Override

Reply via email to