This is an automated email from the ASF dual-hosted git repository. nfilotto pushed a commit to branch 289/auto-configure-spi-providers in repository https://gitbox.apache.org/repos/asf/camel-karaf.git
commit d1ad2bb9201f7b81c27039a8c1c468553ec74036 Author: Nicolas Filotto <nfilo...@talend.com> AuthorDate: Tue Jun 11 16:52:53 2024 +0200 Ref #289: Add SPI-Provider to all wrapped bundles with SPI services --- features/pom.xml | 5 + features/src/main/feature/camel-features.xml | 22 ++-- pom.xml | 3 - tooling/camel-karaf-feature-maven-plugin/pom.xml | 6 + .../karaf/feature/maven/AbstractFeaturesMojo.java | 98 +++++++++++++++ .../feature/maven/AbstractWrapBundleMojo.java | 46 +++++++ .../feature/maven/ConfigureWrapSpiProvider.java | 134 +++++++++++++++++++++ .../feature/maven/EnsureWrapBundleVersionMojo.java | 100 ++------------- 8 files changed, 307 insertions(+), 107 deletions(-) diff --git a/features/pom.xml b/features/pom.xml index 89231593..912c8fd8 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -32,6 +32,10 @@ <packaging>pom</packaging> <name>Apache Camel :: Karaf :: Features</name> + <properties> + <spi-consumer>SPI-Consumer=*</spi-consumer> + </properties> + <dependencies> <dependency> <groupId>org.apache.karaf.features</groupId> @@ -71,6 +75,7 @@ <execution> <goals> <goal>ensure-wrap-bundle-version</goal> + <goal>configure-wrap-spi-provider</goal> </goals> <configuration> <featuresFilePath>file:${project.build.directory}/feature/camel-features.xml</featuresFilePath> diff --git a/features/src/main/feature/camel-features.xml b/features/src/main/feature/camel-features.xml index cf9a3ab2..9a0f5cff 100644 --- a/features/src/main/feature/camel-features.xml +++ b/features/src/main/feature/camel-features.xml @@ -158,13 +158,12 @@ </feature> <feature name="awssdk" version="${aws-java-sdk2-version}" start-level="50"> - <feature prerequisite="true">spifly</feature> <feature version="[4,5)">http-client</feature> <bundle dependency='true'>wrap:mvn:software.amazon.awssdk/auth/${aws-java-sdk2-version}</bundle> <bundle dependency='true'>wrap:mvn:software.amazon.awssdk/aws-core/${aws-java-sdk2-version}</bundle> <bundle dependency='true'>wrap:mvn:software.amazon.awssdk/sdk-core/${aws-java-sdk2-version}$${spi-consumer}</bundle> <bundle dependency='true'>wrap:mvn:software.amazon.awssdk/http-client-spi/${aws-java-sdk2-version}</bundle> - <bundle dependency='true'>wrap:mvn:software.amazon.awssdk/apache-client/${aws-java-sdk2-version}$${spi-provider}</bundle> + <bundle dependency='true'>wrap:mvn:software.amazon.awssdk/apache-client/${aws-java-sdk2-version}</bundle> <bundle dependency='true'>wrap:mvn:software.amazon.awssdk/regions/${aws-java-sdk2-version}</bundle> <bundle dependency='true'>wrap:mvn:software.amazon.awssdk/utils/${aws-java-sdk2-version}</bundle> <bundle dependency='true'>wrap:mvn:software.amazon.awssdk/identity-spi/${aws-java-sdk2-version}</bundle> @@ -338,7 +337,6 @@ </feature> <feature name='camel-atmosphere-websocket' version='${project.version}' start-level='50'> <feature version='${camel.osgi.version.range}'>camel-servlet</feature> - <feature prerequisite="true">spifly</feature> <!-- Wrap protocol used to work around the wrong version range used for the servlet API [2.5,4) --> <bundle dependency="true">wrap:mvn:org.atmosphere/atmosphere-runtime/${atmosphere-version}$overwrite=merge&Import-Package=jakarta.servlet;version:="[6,7)",*;resolution:=optional</bundle> <bundle>mvn:org.apache.camel.karaf/camel-atmosphere-websocket/${project.version}</bundle> @@ -1037,7 +1035,6 @@ <feature version='${camel.osgi.version.range}'>camel-core</feature> <feature version="[33,34)">guava</feature> <feature version='[4.1,5)'>netty</feature> - <feature prerequisite="true">spifly</feature> <bundle dependency='true'>wrap:mvn:com.google.cloud/google-cloud-pubsub/1.127.1</bundle> <bundle dependency='true'>wrap:mvn:com.google.api/api-common/2.28.0</bundle> <bundle dependency='true'>mvn:com.google.protobuf/protobuf-java/${protobuf-version}</bundle> @@ -1064,13 +1061,13 @@ <bundle dependency='true'>wrap:mvn:com.google.api.grpc/proto-google-common-protos/2.36.0$Export-Package=com.google.longrunning*;version=2.36.0,*</bundle> <bundle dependency='true'>wrap:mvn:io.perfmark/perfmark-api/0.27.0</bundle> <bundle dependency='true'>wrap:mvn:io.grpc/grpc-stub/${grpc-version}</bundle> - <bundle dependency='true'>wrap:mvn:io.grpc/grpc-netty/${grpc-version}$${spi-provider}</bundle> - <bundle dependency='true'>wrap:mvn:io.grpc/grpc-core/${grpc-version}$${spi-provider}</bundle> - <bundle dependency='true'>wrap:mvn:io.grpc/grpc-grpclb/${grpc-version}$${spi-provider}</bundle> - <bundle dependency='true'>wrap:mvn:io.grpc/grpc-googleapis/${grpc-version}$${spi-provider}</bundle> - <bundle dependency='true'>wrap:mvn:io.grpc/grpc-xds/${grpc-version}$${spi-provider}</bundle> - <bundle dependency='true'>wrap:mvn:io.grpc/grpc-services/${grpc-version}$${spi-provider}</bundle> - <bundle dependency='true'>wrap:mvn:io.grpc/grpc-util/${grpc-version}$${spi-provider}</bundle> + <bundle dependency='true'>wrap:mvn:io.grpc/grpc-netty/${grpc-version}</bundle> + <bundle dependency='true'>wrap:mvn:io.grpc/grpc-core/${grpc-version}</bundle> + <bundle dependency='true'>wrap:mvn:io.grpc/grpc-grpclb/${grpc-version}</bundle> + <bundle dependency='true'>wrap:mvn:io.grpc/grpc-googleapis/${grpc-version}</bundle> + <bundle dependency='true'>wrap:mvn:io.grpc/grpc-xds/${grpc-version}</bundle> + <bundle dependency='true'>wrap:mvn:io.grpc/grpc-services/${grpc-version}</bundle> + <bundle dependency='true'>wrap:mvn:io.grpc/grpc-util/${grpc-version}</bundle> <bundle>mvn:org.apache.camel.karaf/camel-google-pubsub/${project.version}</bundle> </feature> <feature name='camel-google-secret-manager' version='${project.version}' start-level='50'> @@ -1529,7 +1526,6 @@ <bundle>mvn:org.apache.camel.karaf/camel-kamelet/${project.version}</bundle> </feature> <feature name='camel-kubernetes' version='${project.version}' start-level='50'> - <feature prerequisite="true">spifly</feature> <feature version='${camel.osgi.version.range}'>camel-core</feature> <feature version='${camel.osgi.jackson2.version}'>jackson</feature> <bundle dependency='true'>wrap:mvn:io.fabric8/kubernetes-client/${kubernetes-client-version}</bundle> @@ -1846,7 +1842,6 @@ <bundle>mvn:org.apache.camel.karaf/camel-opensearch/${project.version}</bundle> </feature> <feature name='camel-openstack' version='${project.version}' start-level='50'> - <feature prerequisite="true">spifly</feature> <feature version='${camel.osgi.version.range}'>camel-core</feature> <feature version='${camel.osgi.jackson2.version}'>jackson</feature> <feature version='[33,34)'>guava</feature> @@ -2170,7 +2165,6 @@ <bundle>mvn:org.apache.camel.karaf/camel-servlet/${project.version}</bundle> </feature> <feature name='camel-shiro' version='${project.version}' start-level='50'> - <feature prerequisite="true">spifly</feature> <feature version='${camel.osgi.version.range}'>camel-core</feature> <bundle dependency='true'>mvn:org.apache.shiro/shiro-core/${shiro-version}</bundle> <bundle dependency='true'>mvn:org.apache.shiro/shiro-event/${shiro-version}</bundle> diff --git a/pom.xml b/pom.xml index ea0aa6f1..59074deb 100644 --- a/pom.xml +++ b/pom.xml @@ -563,9 +563,6 @@ <maven-compiler-plugin-version>3.13.0</maven-compiler-plugin-version> <harmcrest.version>1.3_1</harmcrest.version> <geronimo-atinject.version>1.2</geronimo-atinject.version> - - <spi-provider>SPI-Provider=*</spi-provider> - <spi-consumer>SPI-Consumer=*</spi-consumer> </properties> <dependencyManagement> diff --git a/tooling/camel-karaf-feature-maven-plugin/pom.xml b/tooling/camel-karaf-feature-maven-plugin/pom.xml index 6a039ecd..b6f8926d 100644 --- a/tooling/camel-karaf-feature-maven-plugin/pom.xml +++ b/tooling/camel-karaf-feature-maven-plugin/pom.xml @@ -51,6 +51,12 @@ </dependency> <!-- maven plugin --> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> diff --git a/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/AbstractFeaturesMojo.java b/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/AbstractFeaturesMojo.java new file mode 100644 index 00000000..5f0ac537 --- /dev/null +++ b/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/AbstractFeaturesMojo.java @@ -0,0 +1,98 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.camel.karaf.feature.maven; + +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import org.apache.karaf.features.internal.model.Feature; +import org.apache.karaf.features.internal.model.Features; +import org.apache.karaf.features.internal.model.JaxbUtil; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Parameter; + +public abstract class AbstractFeaturesMojo extends AbstractMojo { + + private static final String FILE_PROTOCOL = "file:"; + + private static final String DEFAULT_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"; + private static final String LICENCE_HEADER = """ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +-->"""; + + @Parameter(property = "featuresFilePath", required = true) + private String featuresFilePath; + + public String getFeaturesFilePath() { + return featuresFilePath; + } + + @Override + public void execute() throws MojoExecutionException { + Features featuresData = JaxbUtil.unmarshal(getFeaturesFilePath(), false); + processFeatures(featuresData.getFeature()); + marshal(featuresData); + } + + private void marshal(Features featuresData) throws MojoExecutionException { + try (StringWriter writer = new StringWriter()) { + JaxbUtil.marshal(featuresData, writer); + + String result = writer.toString().replace(DEFAULT_HEADER, LICENCE_HEADER); + + Path path = Paths.get(getFeaturesFilePath().replaceFirst(FILE_PROTOCOL, "")); + Files.writeString(path, result); + + getLog().info("File '%s' was successfully modified and saved".formatted(getFeaturesFilePath())); + } catch (Exception e) { + getLog().error("File '%s' was successfully modified but an error occurred while saving it" + .formatted(getFeaturesFilePath()), e); + throw new MojoExecutionException(e); + } + } + + + private void processFeatures(List<Feature> features) { + for (Feature feature : features) { + processFeature(feature); + } + } + + protected abstract void processFeature(Feature feature); +} diff --git a/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/AbstractWrapBundleMojo.java b/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/AbstractWrapBundleMojo.java new file mode 100644 index 00000000..8ce45436 --- /dev/null +++ b/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/AbstractWrapBundleMojo.java @@ -0,0 +1,46 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.camel.karaf.feature.maven; + +import org.apache.karaf.features.internal.model.Bundle; +import org.apache.karaf.features.internal.model.Feature; + +public abstract class AbstractWrapBundleMojo extends AbstractFeaturesMojo { + + private static final String WRAP_PROTOCOL = "wrap:mvn:"; + + @Override + protected void processFeature(Feature feature) { + boolean processed = false; + for (Bundle bundle : feature.getBundle()) { + String location = bundle.getLocation(); + if (location != null && location.startsWith(WRAP_PROTOCOL)) { + processed |= processWrappedBundle(bundle); + } + } + if (processed) { + onFeatureUpdated(feature); + } + } + + protected void onFeatureUpdated(Feature feature) { + // Do nothing by default + } + + protected abstract boolean processWrappedBundle(Bundle bundle); +} diff --git a/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/ConfigureWrapSpiProvider.java b/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/ConfigureWrapSpiProvider.java new file mode 100644 index 00000000..6a3a4c64 --- /dev/null +++ b/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/ConfigureWrapSpiProvider.java @@ -0,0 +1,134 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.camel.karaf.feature.maven; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.ZipFile; + +import org.apache.karaf.features.internal.model.Bundle; +import org.apache.karaf.features.internal.model.Dependency; +import org.apache.karaf.features.internal.model.Feature; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactRequest; + + +@Mojo(name = "configure-wrap-spi-provider", defaultPhase = LifecyclePhase.PROCESS_RESOURCES) +public class ConfigureWrapSpiProvider extends AbstractWrapBundleMojo { + + private static final Pattern WRAP_PROTOCOL = Pattern.compile("wrap:mvn:([^/]+)/([^/]+)/([^$]+)(\\$([^=]+=[^&]+)(&([^=]+=[^&]+))*)?"); + private static final String SPI_PROVIDER = "SPI-Provider"; + private static final String SPI_HEADER = "%s=*".formatted(SPI_PROVIDER); + + @Component + private RepositorySystem repoSystem; + + @Parameter(defaultValue = "${repositorySystemSession}", readonly = true, required = true) + private RepositorySystemSession repoSession; + + @Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true, required = true) + private List<RemoteRepository> repositories; + + @Override + protected void onFeatureUpdated(Feature feature) { + if (!containsSpiFly(feature)) { + // Add spifly as a prerequisite if not exists + Dependency dependency = new Dependency("spifly", null); + dependency.setPrerequisite(true); + feature.getFeature().add(dependency); + } + } + + private static boolean containsSpiFly(Feature feature) { + return feature.getFeature().stream().anyMatch(d -> "spifly".equals(d.getName())); + } + + @Override + protected boolean processWrappedBundle(Bundle bundle) { + String location = bundle.getLocation(); + Matcher matcher = WRAP_PROTOCOL.matcher(location); + if (matcher.matches()) { + String groupId = matcher.group(1); + String artifactId = matcher.group(2); + String version = matcher.group(3); + String options = matcher.group(4); + if (options != null && options.contains(SPI_PROVIDER)) { + return false; + } else if (provideSPI(groupId, artifactId, version)) { + addHeader(bundle, options, location); + return true; + } + } + return false; + } + + private static void addHeader(Bundle bundle, String options, String location) { + String separator; + if (options == null) { + separator = "$"; + } else if (options.endsWith("&") || options.endsWith("$")) { + separator = ""; + } else { + separator = "&"; + } + bundle.setLocation("%s%s%s".formatted(location, separator, SPI_HEADER)); + } + + private boolean provideSPI(String groupId, String artifactId, String version) { + File file = downloadArtifact(groupId, artifactId, version); + if (file == null) { + getLog().warn("Could not download artifact %s:%s:%s".formatted(groupId, artifactId, version)); + return false; + } + try { + return containsSPI(file); + } catch (IOException e) { + getLog().warn("Could not check artifact %s:%s:%s".formatted(groupId, artifactId, version), e); + } + return false; + } + + private static boolean containsSPI(File file) throws IOException { + try (ZipFile zip = new ZipFile(file)) { + return zip.getEntry("META-INF/services") != null; + } + } + + private File downloadArtifact(String groupId, String artifactId, String version) { + getLog().debug("Downloading artifact %s:%s:%s".formatted(groupId, artifactId, version)); + ArtifactRequest req = new ArtifactRequest() + .setRepositories(this.repositories) + .setArtifact(new DefaultArtifact(groupId, artifactId, "jar", version)); + try { + return this.repoSystem.resolveArtifact(this.repoSession, req).getArtifact().getFile(); + } catch (Exception e) { + getLog().warn("Artifact %s could not be resolved.".formatted(artifactId), e); + } + return null; + } +} diff --git a/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleVersionMojo.java b/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleVersionMojo.java index ef06fe20..bcc92cf9 100644 --- a/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleVersionMojo.java +++ b/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleVersionMojo.java @@ -16,33 +16,19 @@ */ package org.apache.camel.karaf.feature.maven; -import java.io.StringWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import org.apache.felix.utils.version.VersionCleaner; import org.apache.karaf.features.internal.model.Bundle; -import org.apache.karaf.features.internal.model.Feature; -import org.apache.karaf.features.internal.model.Features; -import org.apache.karaf.features.internal.model.JaxbUtil; -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; import org.osgi.framework.Version; @Mojo(name = "ensure-wrap-bundle-version", defaultPhase = LifecyclePhase.PROCESS_RESOURCES) -public class EnsureWrapBundleVersionMojo extends AbstractMojo { +public class EnsureWrapBundleVersionMojo extends AbstractWrapBundleMojo { - private static final String FILE_PROTOCOL = "file:"; - - private static final String WRAP_PROTOCOL = "wrap:mvn:"; - private static final List<String> HEADERS_AFTER_BUNDLE_VEIRSION = Arrays.asList( - //"Bundle-Version", + private static final List<String> HEADERS_AFTER_BUNDLE_VERSION = Arrays.asList( "DynamicImport-Package", "Export-Package", "Export-Service", @@ -53,83 +39,17 @@ public class EnsureWrapBundleVersionMojo extends AbstractMojo { "Require-Bundle", "Require-Capability"); - private static final String DEFAULT_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"; - private static final String LICENCE_HEADER = """ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - - 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. - --->"""; - static final String BUNDLE_VERSION = "Bundle-Version"; - @Parameter(property = "featuresFilePath", required = true) - private String featuresFilePath; - - public String getFeaturesFilePath() { - return featuresFilePath; - } - - public void setFeaturesFilePath(String featuresFilePath) { - this.featuresFilePath = featuresFilePath; - } - @Override - public void execute() throws MojoExecutionException { - Features featuresData = JaxbUtil.unmarshal(getFeaturesFilePath(), false); - processFeatures(featuresData.getFeature()); - - marshal(featuresData); - } - - private void marshal(Features featuresData) throws MojoExecutionException { - try (StringWriter writer = new StringWriter()) { - JaxbUtil.marshal(featuresData, writer); - - String result = writer.toString().replace(DEFAULT_HEADER, LICENCE_HEADER); - - Path path = Paths.get(getFeaturesFilePath().replaceFirst(FILE_PROTOCOL, "")); - Files.writeString(path, result); - - getLog().info("File '%s' was successfully modified and saved".formatted(getFeaturesFilePath())); + protected boolean processWrappedBundle(Bundle bundle) { + String location = bundle.getLocation(); + try { + bundle.setLocation(processLocation(location)); } catch (Exception e) { - getLog().error("File '%s' was successfully modified but an error occurred while saving it" - .formatted(getFeaturesFilePath()), e); - throw new MojoExecutionException(e); - } - } - - private void processFeatures(List<Feature> features) { - for (Feature feature : features) { - processFeature(feature); - } - } - - private void processFeature(Feature feature) { - for (Bundle bundle : feature.getBundle()) { - String location = bundle.getLocation(); - if (location != null && location.startsWith(WRAP_PROTOCOL)) { - try { - bundle.setLocation(processLocation(location)); - } catch (Exception e) { - getLog().error("Could not process the Bundle location '%s': %s".formatted(location, e.getMessage()), e); - } - } + getLog().error("Could not process the Bundle location '%s': %s".formatted(location, e.getMessage()), e); } + return false; } String processLocation(String location) throws Exception { @@ -147,11 +67,11 @@ public class EnsureWrapBundleVersionMojo extends AbstractMojo { return updateExistingVersion(location, bundleVersionHeader); } - String wrapProtocolOptions = location.substring(versionEndIndex + 1, location.length()); + String wrapProtocolOptions = location.substring(versionEndIndex + 1); StringBuilder sb = new StringBuilder(location); // insert before existing headers header - for (String header : HEADERS_AFTER_BUNDLE_VEIRSION) { + for (String header : HEADERS_AFTER_BUNDLE_VERSION) { // add Bundle-Version before if (location.contains(header)) { int versionHeaderStartIndex = location.indexOf(header);