diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2022-01-18 16:53:19 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-18 16:53:19 +0100 |
commit | 8ca62417e9c3b1bb2887226054069fb4c346c835 (patch) | |
tree | c723ea4908c718716bb4533b572834fb1a0a965a | |
parent | 305dd6ca6dd90d8cf1a1f51c6d8575d5f2b3ee67 (diff) | |
parent | 5baecf63ad51430f4458f6594822ed3143dc99d0 (diff) |
Merge pull request #20860 from vespa-engine/bjorncs/validate-pom-repositories
Bjorncs/validate pom repositories
3 files changed, 86 insertions, 32 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 87a84911d3e..fe5ffb4e544 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 @@ -18,6 +18,7 @@ import org.xml.sax.InputSource; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.io.IOException; import java.io.StringReader; @@ -31,6 +32,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Predicate; import java.util.jar.Attributes; import java.util.jar.JarFile; @@ -58,7 +60,7 @@ public class BundleValidator extends Validator { DeployLogger deployLogger = deployState.getDeployLogger(); deployLogger.log(Level.FINE, String.format("Validating bundle at '%s'", path)); JarFile jarFile = new JarFile(app.getFileReference(path)); - validateJarFile(deployLogger, jarFile); + validateJarFile(deployLogger, deployState.isHosted(), jarFile); } catch (IOException e) { throw new IllegalArgumentException( "Failed to validate JAR file '" + path.last() + "'", e); @@ -66,7 +68,7 @@ public class BundleValidator extends Validator { } } - void validateJarFile(DeployLogger deployLogger, JarFile jarFile) throws IOException { + void validateJarFile(DeployLogger deployLogger, boolean isHosted, JarFile jarFile) throws IOException { Manifest manifest = jarFile.getManifest(); String filename = Paths.get(jarFile.getName()).getFileName().toString(); if (manifest == null) { @@ -74,7 +76,7 @@ public class BundleValidator extends Validator { } validateManifest(deployLogger, filename, manifest); getPomXmlContent(deployLogger, jarFile) - .ifPresent(pomXml -> validatePomXml(deployLogger, filename, pomXml)); + .ifPresent(pomXml -> validatePomXml(deployLogger, isHosted, filename, pomXml)); } private void validateManifest(DeployLogger deployLogger, String filename, Manifest mf) { @@ -150,30 +152,60 @@ public class BundleValidator extends Validator { }); } - 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( - "The pom.xml of bundle '%s' includes a dependency to the artifact '%s:%s'. \n%s", - jarFilename, groupId, artifactId, deprecatedArtifact.description)); - } + private void validatePomXml(DeployLogger deployLogger, boolean isHosted, String jarFilename, String pomXmlContent) { + if (isHosted) { + try { + Document pom = DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder() + .parse(new InputSource(new StringReader(pomXmlContent))); + validateDependencies(deployLogger, jarFilename, pom); + validateRepositories(deployLogger, jarFilename, pom); + } 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 static void validateDependencies(DeployLogger deployLogger, String jarFilename, Document pom) throws XPathExpressionException { + forEachPomXmlElement(pom, "dependencies/dependency", dependency -> { + 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( + "The pom.xml of bundle '%s' includes a dependency to the artifact '%s:%s'. \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 static void validateRepositories(DeployLogger deployLogger, String jarFilename, Document pom) throws XPathExpressionException { + forEachPomXmlElement(pom, "pluginRepositories/pluginRepository", + repository -> validateRepository(deployLogger, jarFilename, "pluginRepositories", repository)); + forEachPomXmlElement(pom, "repositories/repository", + repository -> validateRepository(deployLogger, jarFilename, "repositories", repository)); + } + + private static void validateRepository(DeployLogger deployLogger, String jarFilename, String parentElementName, + Element element) { + String url = element.getElementsByTagName("url").item(0).getTextContent(); + if (url.contains("vespa-maven-libs-release-local")) { + deployLogger.logApplicationPackage(Level.WARNING, + String.format("<%s> in pom.xml of '%s' uses deprecated Maven repository '%s'.\n See announcement.", + parentElementName, jarFilename, url)); + } + } + + private static void forEachPomXmlElement(Document pom, String xpath, Consumer<Element> consumer) throws XPathExpressionException { + NodeList dependencies = (NodeList) XPathFactory.newDefaultInstance().newXPath() + .compile("/project/" + xpath) + .evaluate(pom, XPathConstants.NODESET); + for (int i = 0; i < dependencies.getLength(); i++) { + Element element = (Element) dependencies.item(i); + consumer.accept(element); } } 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 index 1d28f307824..167751f55c4 100644 --- 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 @@ -12,4 +12,17 @@ <scope>test</scope> </dependency> </dependencies> + + <pluginRepositories> + <pluginRepository> + <id>my-plugin-repository</id> + <url>http://myartifactory:8000/artifactory/vespa-maven-libs-release-local</url> + </pluginRepository> + </pluginRepositories> + <repositories> + <repository> + <id>my-repository</id> + <url>http://myartifactory:8000/artifactory/vespa-maven-libs-release-local</url> + </repository> + </repositories> </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 ef4353d02fb..eeae7dfe0ee 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 @@ -29,7 +29,7 @@ public class BundleValidatorTest { // Valid jar file JarFile ok = createTemporaryJarFile("ok"); BundleValidator bundleValidator = new BundleValidator(); - bundleValidator.validateJarFile(new BaseDeployLogger(), ok); + bundleValidator.validateJarFile(new BaseDeployLogger(), false, ok); // No manifest validateWithException("nomanifest", "Non-existing or invalid manifest in nomanifest.jar"); @@ -39,7 +39,7 @@ public class BundleValidatorTest { try { JarFile jarFile = createTemporaryJarFile(jarName); BundleValidator bundleValidator = new BundleValidator(); - bundleValidator.validateJarFile(new BaseDeployLogger(), jarFile); + bundleValidator.validateJarFile(new BaseDeployLogger(), false, jarFile); assert (false); } catch (IllegalArgumentException e) { assertEquals(e.getMessage(), exceptionMessage); @@ -52,7 +52,7 @@ public class BundleValidatorTest { DeployLogger logger = createDeployLogger(buffer); JarFile jarFile = createTemporaryJarFile("snapshot_bundle"); - new BundleValidator().validateJarFile(logger, jarFile); + new BundleValidator().validateJarFile(logger, false, jarFile); assertTrue(buffer.toString().contains("Deploying snapshot bundle")); } @@ -62,7 +62,7 @@ public class BundleValidatorTest { DeployLogger logger = createDeployLogger(buffer); BundleValidator validator = new BundleValidator(); JarFile jarFile = createTemporaryJarFile("import-warnings"); - validator.validateJarFile(logger, jarFile); + validator.validateJarFile(logger, true, jarFile); assertThat(buffer.toString()) .contains("For JAR file 'import-warnings.jar': \n" + "Manifest imports the following Java packages from 'org.json:json': [org.json]. \n" + @@ -70,18 +70,27 @@ public class BundleValidatorTest { } @Test - public void outputs_deploy_warning_on_deprecated_dependency() throws IOException { + public void outputs_deploy_warnings_for_pom_xml() 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()) + validator.validateJarFile(logger, true, jarFile); + String output = buffer.toString(); + assertThat(output) .contains("The pom.xml of bundle 'pom-xml-warnings.jar' includes a dependency to the artifact " + "'com.yahoo.vespa:vespa-http-client-extensions'. \n" + "This 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.\n"); + assertThat(output) + .contains("\n" + + "<pluginRepositories> in pom.xml of 'pom-xml-warnings.jar' uses deprecated Maven repository " + + "'http://myartifactory:8000/artifactory/vespa-maven-libs-release-local'.\n See announcement."); + assertThat(output) + .contains("\n" + + "<repositories> in pom.xml of 'pom-xml-warnings.jar' uses deprecated Maven repository " + + "'http://myartifactory:8000/artifactory/vespa-maven-libs-release-local'.\n See announcement."); } private JarFile createTemporaryJarFile(String testArtifact) throws IOException { |