Skip to content

Commit 5e4167f

Browse files
authored
fix(karaf-maven-plugin): Deal with non-features classifier in the karaf-maven-plugin (#2521)
1 parent 7a3f8f8 commit 5e4167f

2 files changed

Lines changed: 56 additions & 8 deletions

File tree

tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626
import java.util.Collection;
2727
import java.util.Comparator;
2828
import java.util.HashMap;
29+
import java.util.HashSet;
2930
import java.util.LinkedHashSet;
3031
import java.util.List;
3132
import java.util.Map;
33+
import java.util.Set;
3234
import java.util.jar.JarInputStream;
3335
import java.util.jar.Manifest;
3436

@@ -37,6 +39,7 @@
3739
import javax.xml.stream.XMLStreamException;
3840

3941
import org.apache.karaf.features.internal.model.*;
42+
import org.apache.karaf.tooling.utils.Dependency31Helper;
4043
import org.apache.karaf.tooling.utils.DependencyHelper;
4144
import org.apache.karaf.tooling.utils.DependencyHelperFactory;
4245
import org.apache.karaf.tooling.utils.LocalDependency;
@@ -490,6 +493,7 @@ private void writeFeatures(PrintStream out) throws ArtifactResolutionException,
490493
// TODO Initialise the repositories from the existing feature file if any
491494
Map<Dependency, Feature> otherFeatures = new HashMap<>();
492495
Map<Feature, String> featureRepositories = new HashMap<>();
496+
Set<Object> recognizedFeatures = new HashSet<>();
493497
FeaturesCache cache = new FeaturesCache(featuresCacheSize, artifactCacheSize);
494498
for (final LocalDependency entry : localDependencies) {
495499
Object artifact = entry.getArtifact();
@@ -499,7 +503,7 @@ private void writeFeatures(PrintStream out) throws ArtifactResolutionException,
499503
}
500504

501505
processFeatureArtifact(features, feature, otherFeatures, featureRepositories, cache, artifact,
502-
entry.getParent(), true);
506+
entry.getParent(), true, recognizedFeatures);
503507
}
504508
// Do not retain cache beyond this point
505509
cache = null;
@@ -514,7 +518,7 @@ private void writeFeatures(PrintStream out) throws ArtifactResolutionException,
514518
continue;
515519
}
516520

517-
if (!this.dependencyHelper.isArtifactAFeature(artifact)) {
521+
if (!this.dependencyHelper.isArtifactAFeature(artifact) && !recognizedFeatures.contains(artifact)) {
518522
String bundleName = this.dependencyHelper.artifactToMvn(artifact, getVersionOrRange(entry.getParent(), artifact));
519523

520524
for (ConfigFile cf : feature.getConfigfile()) {
@@ -609,19 +613,33 @@ private void writeFeatures(PrintStream out) throws ArtifactResolutionException,
609613

610614
private void processFeatureArtifact(Features features, Feature feature, Map<Dependency, Feature> otherFeatures,
611615
Map<Feature, String> featureRepositories, FeaturesCache cache,
612-
Object artifact, Object parent, boolean add)
616+
Object artifact, Object parent, boolean add, Set<Object> recognizedFeatures)
613617
throws MojoExecutionException, XMLStreamException, JAXBException, IOException {
614-
if (this.dependencyHelper.isArtifactAFeature(artifact) && FEATURE_CLASSIFIER.equals(
615-
this.dependencyHelper.getClassifier(artifact))) {
616-
File featuresFile = this.dependencyHelper.resolve(artifact, getLog());
618+
boolean isFeature = this.dependencyHelper.isArtifactAFeature(artifact);
619+
File featuresFile = null;
620+
if (!isFeature) {
621+
// For XML artifacts with non-standard classifiers, resolve and check content
622+
featuresFile = this.dependencyHelper.resolve(artifact, getLog());
623+
if (featuresFile != null && featuresFile.exists()
624+
&& Dependency31Helper.isFeaturesXml(featuresFile)) {
625+
isFeature = true;
626+
}
627+
}
628+
if (isFeature) {
629+
if (recognizedFeatures != null) {
630+
recognizedFeatures.add(artifact);
631+
}
632+
if (featuresFile == null) {
633+
featuresFile = this.dependencyHelper.resolve(artifact, getLog());
634+
}
617635
if (featuresFile == null || !featuresFile.exists()) {
618636
throw new MojoExecutionException(
619637
"Cannot locate file for feature: " + artifact + " at " + featuresFile);
620638
}
621639
Features includedFeatures = cache.getFeature(featuresFile);
622640
for (String repository : includedFeatures.getRepository()) {
623641
processFeatureArtifact(features, feature, otherFeatures, featureRepositories, cache,
624-
cache.getArtifact(repository), parent, false);
642+
cache.getArtifact(repository), parent, false, recognizedFeatures);
625643
}
626644
for (Feature includedFeature : includedFeatures.getFeature()) {
627645
Dependency dependency = new Dependency(includedFeature.getName(), includedFeature.getVersion());

tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/Dependency31Helper.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,16 @@
4343
import org.codehaus.plexus.util.StringUtils;
4444

4545
import java.io.File;
46+
import java.io.FileInputStream;
47+
import java.io.InputStream;
4648
import java.lang.reflect.InvocationTargetException;
4749
import java.lang.reflect.Method;
4850
import java.util.*;
4951

52+
import javax.xml.namespace.QName;
53+
import javax.xml.stream.XMLInputFactory;
54+
import javax.xml.stream.XMLStreamReader;
55+
5056
import static java.lang.String.*;
5157
import static org.apache.commons.lang3.reflect.MethodUtils.invokeMethod;
5258
import static org.apache.karaf.deployer.kar.KarArtifactInstaller.FEATURE_CLASSIFIER;
@@ -284,7 +290,31 @@ public static boolean isFeature(DependencyNode dependencyNode) {
284290
}
285291

286292
public static boolean isFeature(Artifact artifact) {
287-
return artifact.getExtension().equals("kar") || FEATURE_CLASSIFIER.equals(artifact.getClassifier());
293+
if (artifact.getExtension().equals("kar") || FEATURE_CLASSIFIER.equals(artifact.getClassifier())) {
294+
return true;
295+
}
296+
// For XML artifacts with non-standard classifiers, check actual content when the file is available
297+
if ("xml".equals(artifact.getExtension()) && artifact.getFile() != null && artifact.getFile().exists()) {
298+
return isFeaturesXml(artifact.getFile());
299+
}
300+
return false;
301+
}
302+
303+
public static boolean isFeaturesXml(File file) {
304+
try (InputStream is = new FileInputStream(file)) {
305+
XMLInputFactory xif = XMLInputFactory.newFactory();
306+
xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
307+
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
308+
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
309+
XMLStreamReader r = xif.createXMLStreamReader(is);
310+
r.nextTag();
311+
QName name = r.getName();
312+
return name.getLocalPart().equals("features")
313+
&& (name.getNamespaceURI().isEmpty()
314+
|| name.getNamespaceURI().startsWith("http://karaf.apache.org/xmlns/features/"));
315+
} catch (Exception e) {
316+
return false;
317+
}
288318
}
289319

290320
@Override

0 commit comments

Comments
 (0)