From d9cadcbc6c6e2b85cb0bbe3649071a8b3fcc5135 Mon Sep 17 00:00:00 2001 From: Jean Francois Denise Date: Tue, 30 Apr 2024 09:39:16 +0200 Subject: [PATCH] Fix for GAL-362, FeaturePackDescriber should not limit to packages and layers --- .../galleon/layout/FeaturePackDescriber.java | 89 ++++++++++++++++++- .../layout/FeaturePackDescription.java | 26 +++++- 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/jboss/galleon/layout/FeaturePackDescriber.java b/core/src/main/java/org/jboss/galleon/layout/FeaturePackDescriber.java index dba8135f..058eae03 100644 --- a/core/src/main/java/org/jboss/galleon/layout/FeaturePackDescriber.java +++ b/core/src/main/java/org/jboss/galleon/layout/FeaturePackDescriber.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 Red Hat, Inc. and/or its affiliates + * Copyright 2016-2024 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,6 +24,8 @@ import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; import javax.xml.stream.XMLStreamException; import org.jboss.galleon.BaseErrors; @@ -32,12 +34,16 @@ import org.jboss.galleon.Errors; import org.jboss.galleon.ProvisioningDescriptionException; import org.jboss.galleon.ProvisioningException; +import org.jboss.galleon.config.ConfigModel; import org.jboss.galleon.spec.ConfigLayerSpec; import org.jboss.galleon.spec.FeaturePackSpec; +import org.jboss.galleon.spec.FeatureSpec; import org.jboss.galleon.spec.PackageSpec; import org.jboss.galleon.util.ZipUtils; import org.jboss.galleon.xml.ConfigLayerSpecXmlParser; +import org.jboss.galleon.xml.ConfigXmlParser; import org.jboss.galleon.xml.FeaturePackXmlParser; +import org.jboss.galleon.xml.FeatureSpecXmlParser; import org.jboss.galleon.xml.PackageXmlParser; import org.jboss.galleon.xml.XmlParsers; @@ -103,10 +109,39 @@ public static FeaturePackDescription describeFeaturePack(Path fpDir, String enco if(Files.exists(layersDir)) { processLayers(layoutBuilder, layersDir, encoding); } - + final Path featuresDir = fpDir.resolve(Constants.FEATURES); + if(Files.exists(featuresDir)) { + processFeatures(layoutBuilder, featuresDir, encoding); + } + final Path configsDir = fpDir.resolve(Constants.CONFIGS); + if(Files.exists(configsDir)) { + processConfigs(layoutBuilder, configsDir, encoding); + } return layoutBuilder.build(); } + private static void processFeatures(FeaturePackDescription.Builder fpBuilder, Path layersDir, String encoding) throws ProvisioningDescriptionException { + assertDirectory(layersDir); + try (DirectoryStream stream = Files.newDirectoryStream(layersDir)) { + for(Path path : stream) { + fpBuilder.addFeature(processFeature(path, encoding)); + } + } catch (IOException e) { + failedToReadDirectory(layersDir, e); + } + } + + private static void processConfigs(FeaturePackDescription.Builder fpBuilder, Path configsDir, String encoding) throws ProvisioningDescriptionException { + assertDirectory(configsDir); + try (DirectoryStream stream = Files.newDirectoryStream(configsDir)) { + for(Path path : stream) { + processConfigModel(path, encoding, fpBuilder); + } + } catch (IOException e) { + failedToReadDirectory(configsDir, e); + } + } + private static void processLayers(FeaturePackDescription.Builder fpBuilder, Path layersDir, String encoding) throws ProvisioningDescriptionException { assertDirectory(layersDir); try (DirectoryStream stream = Files.newDirectoryStream(layersDir)) { @@ -142,6 +177,56 @@ private static ConfigLayerSpec processLayer(Path layerDir, String encoding) thro throw new ProvisioningDescriptionException(Errors.parseXml(layerXml), e); } } + private static FeatureSpec processFeature(Path featureDir, String encoding) throws ProvisioningDescriptionException { + assertDirectory(featureDir); + final Path featureXml = featureDir.resolve(Constants.SPEC_XML); + if(!Files.exists(featureXml)) { + throw new ProvisioningDescriptionException(BaseErrors.pathDoesNotExist(featureXml)); + } + try (Reader in = Files.newBufferedReader(featureXml, Charset.forName(encoding))) { + return FeatureSpecXmlParser.getInstance().parse(in); + } catch (IOException e) { + throw new ProvisioningDescriptionException(Errors.openFile(featureXml), e); + } catch (XMLStreamException e) { + throw new ProvisioningDescriptionException(Errors.parseXml(featureXml), e); + } + } + + private static void processConfigModel(Path configDir, String encoding, FeaturePackDescription.Builder fpBuilder) throws ProvisioningDescriptionException { + assertDirectory(configDir); + ConfigModel model = null; + Map configs = new HashMap<>(); + String modelName = configDir.getFileName().toString(); + final Path modelXml = configDir.resolve(Constants.MODEL_XML); + if (Files.exists(modelXml)) { + try (Reader in = Files.newBufferedReader(modelXml, Charset.forName(encoding))) { + model = ConfigXmlParser.getInstance().parse(in); + } catch (IOException e) { + throw new ProvisioningDescriptionException(Errors.openFile(modelXml), e); + } catch (XMLStreamException e) { + throw new ProvisioningDescriptionException(Errors.parseXml(modelXml), e); + } + configs.put(Constants.MODEL_XML, model); + } + try (DirectoryStream stream = Files.newDirectoryStream(configDir)) { + for (Path path : stream) { + String configName = path.getFileName().toString(); + final Path configXml = path.resolve(Constants.CONFIG_XML); + if (Files.exists(configXml)) { + try (Reader in = Files.newBufferedReader(configXml, Charset.forName(encoding))) { + configs.put(configName, ConfigXmlParser.getInstance().parse(in)); + } catch (IOException e) { + throw new ProvisioningDescriptionException(Errors.openFile(modelXml), e); + } catch (XMLStreamException e) { + throw new ProvisioningDescriptionException(Errors.parseXml(modelXml), e); + } + } + } + } catch (IOException e) { + failedToReadDirectory(configDir, e); + } + fpBuilder.addConfigModel(modelName, configs); + } private static PackageSpec processPackage(Path pkgDir, String encoding) throws ProvisioningDescriptionException { assertDirectory(pkgDir); diff --git a/core/src/main/java/org/jboss/galleon/layout/FeaturePackDescription.java b/core/src/main/java/org/jboss/galleon/layout/FeaturePackDescription.java index dee124ea..037dbfd7 100644 --- a/core/src/main/java/org/jboss/galleon/layout/FeaturePackDescription.java +++ b/core/src/main/java/org/jboss/galleon/layout/FeaturePackDescription.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 Red Hat, Inc. and/or its affiliates + * Copyright 2016-2024 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,8 +26,10 @@ import org.jboss.galleon.Errors; import org.jboss.galleon.ProvisioningDescriptionException; +import org.jboss.galleon.config.ConfigModel; import org.jboss.galleon.spec.ConfigLayerSpec; import org.jboss.galleon.spec.FeaturePackSpec; +import org.jboss.galleon.spec.FeatureSpec; import org.jboss.galleon.spec.PackageDependencySpec; import org.jboss.galleon.spec.PackageSpec; import org.jboss.galleon.universe.FeaturePackLocation; @@ -49,6 +51,8 @@ public static class Builder { private final FeaturePackSpec.Builder spec; private Map packages = Collections.emptyMap(); private Map layers = Collections.emptyMap(); + private Map features = Collections.emptyMap(); + private Map> configModels = Collections.emptyMap(); private Builder(FeaturePackLocation.FPID fpid, FeaturePackSpec.Builder spec) { this.fpid = fpid; @@ -65,6 +69,11 @@ public Builder addLayer(ConfigLayerSpec layer) { return this; } + public Builder addFeature(FeatureSpec spec) { + features = CollectionUtils.put(features, spec.getName(), spec); + return this; + } + public boolean hasPackage(String name) { return packages.containsKey(name); } @@ -76,6 +85,11 @@ public FeaturePackSpec.Builder getSpecBuilder() { public FeaturePackDescription build() throws ProvisioningDescriptionException { return new FeaturePackDescription(this); } + + public Builder addConfigModel(String modelName, Map configs) { + configModels = CollectionUtils.put(configModels, modelName, configs); + return this; + } } public static Builder builder(FeaturePackSpec.Builder spec) { @@ -86,6 +100,8 @@ public static Builder builder(FeaturePackSpec.Builder spec) { private final FeaturePackSpec spec; private final Map packages; private final Map layers; + private final Map features; + private final Map> configModels; final List unresolvedLocalPkgs; final boolean externalPkgDeps; @@ -131,6 +147,8 @@ private FeaturePackDescription(Builder builder) throws ProvisioningDescriptionEx } } this.layers = CollectionUtils.unmodifiable(builder.layers); + this.features = CollectionUtils.unmodifiable(builder.features); + this.configModels = CollectionUtils.unmodifiable(builder.configModels); this.externalPkgDeps = externalPkgDeps; this.unresolvedLocalPkgs = CollectionUtils.unmodifiable(notFound); } @@ -165,4 +183,10 @@ public Collection getPackages() { public Collection getLayers() { return layers.values(); } + public Collection getFeatures() { + return features.values(); + } + public Map> getConfigs() { + return configModels; + } } \ No newline at end of file