aboutsummaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2022-01-13 11:57:54 +0100
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2022-01-13 11:57:54 +0100
commitcfdd42d95c39a064abaacd659bf0e09a206aa818 (patch)
tree9b2ce2906151eae5a4a1118a04b94660ecaec20c /config-model
parentd4c30771a13f9f3df9edf234fe324ca4dad8b3cb (diff)
Warn on deprecated Maven artifacts in pom.xml
Also change deprecated bundle logic to use regex matcher for Java package name.
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/BundleValidator.java114
-rw-r--r--config-model/src/test/cfg/application/validation/testjars/pom-xml-warnings/META-INF/MANIFEST.MF7
-rw-r--r--config-model/src/test/cfg/application/validation/testjars/pom-xml-warnings/META-INF/maven/com.yahoo.test/mybundle/pom.xml15
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/BundleValidatorTest.java14
4 files changed, 133 insertions, 17 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/BundleValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/BundleValidator.java
index 04d4ac35e6a..d89d2f166cd 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/BundleValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/BundleValidator.java
@@ -10,8 +10,17 @@ import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.path.Path;
import com.yahoo.vespa.model.VespaModel;
-
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
import java.io.IOException;
+import java.io.StringReader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
@@ -20,12 +29,15 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Level;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/**
* A validator for bundles. Uses BND library for some of the validation.
@@ -61,6 +73,8 @@ public class BundleValidator extends Validator {
throw new IllegalArgumentException("Non-existing or invalid manifest in " + filename);
}
validateManifest(deployLogger, filename, manifest);
+ getPomXmlContent(deployLogger, jarFile)
+ .ifPresent(pomXml -> validatePomXml(deployLogger, filename, pomXml));
}
private void validateManifest(DeployLogger deployLogger, String filename, Manifest mf) {
@@ -92,18 +106,20 @@ public class BundleValidator extends Validator {
private static void validateImportedPackages(DeployLogger deployLogger, String filename, Manifest manifest) {
Domain osgiHeaders = Domain.domain(manifest);
Parameters importPackage = osgiHeaders.getImportPackage();
- Map<DeprecatedArtifact, List<String>> deprecatedPackagesInUse = new HashMap<>();
+ Map<DeprecatedProvidedBundle, List<String>> deprecatedPackagesInUse = new HashMap<>();
importPackage.forEach((packageName, attrs) -> {
VersionRange versionRange = attrs.getVersion() != null
? VersionRange.parseOSGiVersionRange(attrs.getVersion())
: null;
- for (DeprecatedArtifact deprecatedArtifact : DeprecatedArtifact.values()) {
- if (deprecatedArtifact.javaPackages.contains(packageName)
- && (versionRange == null || deprecatedArtifact.versionDiscriminator.test(versionRange))) {
- deprecatedPackagesInUse.computeIfAbsent(deprecatedArtifact, __ -> new ArrayList<>())
- .add(packageName);
+ for (DeprecatedProvidedBundle deprecatedBundle : DeprecatedProvidedBundle.values()) {
+ for (Predicate<String> matcher : deprecatedBundle.javaPackageMatchers) {
+ if (matcher.test(packageName)
+ && (versionRange == null || deprecatedBundle.versionDiscriminator.test(versionRange))) {
+ deprecatedPackagesInUse.computeIfAbsent(deprecatedBundle, __ -> new ArrayList<>())
+ .add(packageName);
+ }
}
}
});
@@ -117,27 +133,91 @@ public class BundleValidator extends Validator {
});
}
- private enum DeprecatedArtifact {
+ private static final Pattern POM_FILE_LOCATION = Pattern.compile("META-INF/maven/.+?/.+?/pom.xml");
+
+ private Optional<String> getPomXmlContent(DeployLogger deployLogger, JarFile jarFile) {
+ return jarFile.stream()
+ .filter(f -> POM_FILE_LOCATION.matcher(f.getName()).matches())
+ .findFirst()
+ .map(f -> {
+ try {
+ return new String(jarFile.getInputStream(f).readAllBytes());
+ } catch (IOException e) {
+ deployLogger.log(Level.INFO,
+ String.format("Unable to read '%s' from '%s'", f.getName(), jarFile.getName()));
+ return null;
+ }
+ });
+ }
+
+ private void validatePomXml(DeployLogger deployLogger, String jarFilename, String pomXmlContent) {
+ try {
+ Document pom = DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder()
+ .parse(new InputSource(new StringReader(pomXmlContent)));
+ NodeList dependencies = (NodeList) XPathFactory.newDefaultInstance().newXPath()
+ .compile("/project/dependencies/dependency")
+ .evaluate(pom, XPathConstants.NODESET);
+ for (int i = 0; i < dependencies.getLength(); i++) {
+ Element dependency = (Element) dependencies.item(i);
+ String groupId = dependency.getElementsByTagName("groupId").item(0).getTextContent();
+ String artifactId = dependency.getElementsByTagName("artifactId").item(0).getTextContent();
+ for (DeprecatedMavenArtifact deprecatedArtifact : DeprecatedMavenArtifact.values()) {
+ if (groupId.equals(deprecatedArtifact.groupId) && artifactId.equals(deprecatedArtifact.artifactId)) {
+ deployLogger.logApplicationPackage(Level.WARNING,
+ String.format("For pom.xml in '%s': \n" +
+ "The dependency %s:%s is listed below dependencies. \n" +
+ "%s",
+ jarFilename, groupId, artifactId, deprecatedArtifact.description));
+ }
+ }
+ }
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ deployLogger.log(Level.INFO, String.format("Unable to parse pom.xml from %s", jarFilename));
+ }
+ }
+
+ private enum DeprecatedMavenArtifact {
+ VESPA_HTTP_CLIENT_EXTENSION("com.yahoo.vespa", "vespa-http-client-extensions",
+ "The 'vespa-http-client-extensions' artifact will be removed in Vespa 8. " +
+ "Programmatic use can be safely removed from system/staging tests. " +
+ "See internal Vespa 8 release notes for details.");
+
+ final String groupId;
+ final String artifactId;
+ final String description;
+
+ DeprecatedMavenArtifact(String groupId, String artifactId, String description) {
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.description = description;
+ }
+ }
+
+ private enum DeprecatedProvidedBundle {
ORG_JSON("org.json:json",
"The org.json library will no longer provided by jdisc runtime on Vespa 8. " +
"See https://docs.vespa.ai/en/vespa8-release-notes.html#container-runtime.",
- Set.of("org.json"));
+ Set.of("org\\.json"));
final String name;
- final Collection<String> javaPackages;
+ final Collection<Predicate<String>> javaPackageMatchers;
final Predicate<VersionRange> versionDiscriminator;
final String description;
- DeprecatedArtifact(String name, String description, Collection<String> javaPackages) {
- this(name, description, __ -> true, javaPackages);
+ DeprecatedProvidedBundle(String name, String description, Collection<String> javaPackagePatterns) {
+ this(name, description, __ -> true, javaPackagePatterns);
}
- DeprecatedArtifact(String name,
- String description,
- Predicate<VersionRange> versionDiscriminator,
- Collection<String> javaPackages) {
+ DeprecatedProvidedBundle(String name,
+ String description,
+ Predicate<VersionRange> versionDiscriminator,
+ Collection<String> javaPackagePatterns) {
this.name = name;
- this.javaPackages = javaPackages;
+ this.javaPackageMatchers = javaPackagePatterns.stream()
+ .map(s -> Pattern.compile(s).asMatchPredicate())
+ .collect(Collectors.toList());
this.versionDiscriminator = versionDiscriminator;
this.description = description;
}
diff --git a/config-model/src/test/cfg/application/validation/testjars/pom-xml-warnings/META-INF/MANIFEST.MF b/config-model/src/test/cfg/application/validation/testjars/pom-xml-warnings/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..1f88a5e6477
--- /dev/null
+++ b/config-model/src/test/cfg/application/validation/testjars/pom-xml-warnings/META-INF/MANIFEST.MF
@@ -0,0 +1,7 @@
+Manifest-Version: 1.0
+Created-By: 1.6.0_20 (Apple Inc.)
+Bundle-ManifestVersion: 2
+Bundle-Name: mybundle
+Bundle-SymbolicName: mybundle
+Bundle-Version: 0
+
diff --git a/config-model/src/test/cfg/application/validation/testjars/pom-xml-warnings/META-INF/maven/com.yahoo.test/mybundle/pom.xml b/config-model/src/test/cfg/application/validation/testjars/pom-xml-warnings/META-INF/maven/com.yahoo.test/mybundle/pom.xml
new file mode 100644
index 00000000000..1d28f307824
--- /dev/null
+++ b/config-model/src/test/cfg/application/validation/testjars/pom-xml-warnings/META-INF/maven/com.yahoo.test/mybundle/pom.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.yahoo.test</groupId>
+ <artifactId>mybundle</artifactId>
+ <packaging>container-plugin</packaging>
+ <version>1.0.0</version>
+ <dependencies>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>vespa-http-client-extensions</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/BundleValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/BundleValidatorTest.java
index ae508c6a388..5532a2d1e3a 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/BundleValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/BundleValidatorTest.java
@@ -69,6 +69,20 @@ public class BundleValidatorTest {
"The org.json library will no longer provided by jdisc runtime on Vespa 8. See https://docs.vespa.ai/en/vespa8-release-notes.html#container-runtime.");
}
+ @Test
+ public void outputs_deploy_warning_on_deprecated_dependency() throws IOException {
+ StringBuffer buffer = new StringBuffer();
+ DeployLogger logger = createDeployLogger(buffer);
+ BundleValidator validator = new BundleValidator();
+ JarFile jarFile = createTemporaryJarFile("pom-xml-warnings");
+ validator.validateJarFile(logger, jarFile);
+ assertThat(buffer.toString())
+ .contains("For pom.xml in 'pom-xml-warnings.jar': \n" +
+ "The dependency com.yahoo.vespa:vespa-http-client-extensions is listed below dependencies. \n" +
+ "The 'vespa-http-client-extensions' artifact will be removed in Vespa 8. " +
+ "Programmatic use can be safely removed from system/staging tests. See internal Vespa 8 release notes for details.");
+ }
+
private JarFile createTemporaryJarFile(String testArtifact) throws IOException {
Path jarFile = tempDir.newFile(testArtifact + ".jar").toPath();
Path artifactDirectory = Paths.get("src/test/cfg/application/validation/testjars/" + testArtifact);