aboutsummaryrefslogtreecommitdiffstats
path: root/bundle-plugin
diff options
context:
space:
mode:
authorgjoranv <gv@yahooinc.com>2023-06-01 13:12:58 +0200
committergjoranv <gv@yahooinc.com>2023-06-01 13:38:13 +0200
commit28e10125cd97ee7846f72bce4a42b1ea1ccca027 (patch)
treefb61b0f13c493148530970b37d572cd6398ca583 /bundle-plugin
parenta84e782c247478572752896cc5488575bda326d8 (diff)
Warn when a USER bundle imports non-PublicApi packages.
Diffstat (limited to 'bundle-plugin')
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/bundle/AnalyzeBundle.java18
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/Packages.java21
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java16
3 files changed, 54 insertions, 1 deletions
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/bundle/AnalyzeBundle.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/bundle/AnalyzeBundle.java
index fe3d149a308..af6c82023ab 100644
--- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/bundle/AnalyzeBundle.java
+++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/bundle/AnalyzeBundle.java
@@ -7,12 +7,14 @@ import com.yahoo.container.plugin.util.JarFiles;
import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.jar.Manifest;
+import java.util.stream.Collectors;
/**
* Static utilities for analyzing jar files.
@@ -43,6 +45,22 @@ public class AnalyzeBundle {
}
}
+ public static List<String> publicApiPackagesAggregated(Collection<File> jarFiles) {
+ return jarFiles.stream()
+ .map(AnalyzeBundle::publicApiPackages)
+ .flatMap(List::stream)
+ .distinct()
+ .toList();
+ }
+
+ static List<String> publicApiPackages(File jarFile) {
+ var manifest = getOsgiManifest(jarFile);
+ if (manifest == null) return Collections.emptyList();
+ return getMainAttributeValue(manifest, "X-JDisc-PublicApi-Package")
+ .map(s -> Arrays.asList(s.split(",")))
+ .orElseGet(ArrayList::new);
+ }
+
private static Manifest getOsgiManifest(File jarFile) {
Optional<Manifest> jarManifest = JarFiles.getManifest(jarFile);
if (jarManifest.isPresent()) {
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/Packages.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/Packages.java
index 9eef8a55c01..48a128c2f0d 100644
--- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/Packages.java
+++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/Packages.java
@@ -1,8 +1,13 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.plugin.classanalysis;
+import com.yahoo.container.plugin.osgi.ImportPackages;
+
import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* Utility methods related to packages.
@@ -31,6 +36,22 @@ public class Packages {
}
}
+ /**
+ * Returns the imported Vespa packages that don't exist in the given set of allowed packages.
+ */
+ public static List<String> disallowedVespaImports(Map<String, ImportPackages.Import> imports, List<String> allowed) {
+ if (imports == null || imports.isEmpty()) return List.of();
+
+ var publicApi = allowed == null ? Set.of() : new HashSet<>(allowed);
+
+ Set<String> yahooImports = imports.keySet().stream()
+ .filter(pkg -> pkg.startsWith("com.yahoo") || pkg.startsWith("ai.vespa."))
+ .collect(Collectors.toSet());
+
+ List<String> disallowedImports = yahooImports.stream().collect(Collectors.groupingBy(publicApi::contains)).get(false);
+ return disallowedImports == null ? List.of() : disallowedImports;
+ }
+
public static PackageMetaData analyzePackages(Set<ClassFileMetaData> allClasses) {
Set<String> definedPackages = new HashSet<>();
Set<String> referencedPackages = new HashSet<>();
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java
index d1c6c5d20c3..d5c9d905a16 100644
--- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java
+++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java
@@ -26,6 +26,8 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.yahoo.container.plugin.bundle.AnalyzeBundle.exportedPackagesAggregated;
+import static com.yahoo.container.plugin.bundle.AnalyzeBundle.publicApiPackagesAggregated;
+import static com.yahoo.container.plugin.classanalysis.Packages.disallowedVespaImports;
import static com.yahoo.container.plugin.osgi.ExportPackages.exportsByPackageName;
import static com.yahoo.container.plugin.osgi.ImportPackages.calculateImports;
import static com.yahoo.container.plugin.util.Files.allDescendantFiles;
@@ -79,7 +81,9 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
throwIfInternalContainerArtifactsAreIncluded(artifactSet.getJarArtifactsToInclude());
List<Artifact> providedJarArtifacts = artifactSet.getJarArtifactsProvided();
- List<Export> exportedPackagesFromProvidedJars = exportedPackagesAggregated(providedJarArtifacts.stream().map(Artifact::getFile).toList());
+ List<File> providedJarFiles = providedJarArtifacts.stream().map(Artifact::getFile).toList();
+ List<Export> exportedPackagesFromProvidedJars = exportedPackagesAggregated(providedJarFiles);
+ List<String> publicApiPackagesFromProvidedJars = publicApiPackagesAggregated(providedJarFiles);
// Packages from Export-Package/PublicApi headers in provided scoped jars
Set<String> exportedPackagesFromProvidedDeps = ExportPackages.packageNames(exportedPackagesFromProvidedJars);
@@ -109,6 +113,7 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
includedPackages.definedPackages(),
exportsByPackageName(exportedPackagesFromProvidedJars));
+ logNonPublicApiUsage(calculatedImports, publicApiPackagesFromProvidedJars);
Map<String, String> manifestContent = generateManifestContent(artifactSet.getJarArtifactsToInclude(), calculatedImports, includedPackages);
addAdditionalManifestProperties(manifestContent, includedPackages);
@@ -119,6 +124,15 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
}
}
+ private void logNonPublicApiUsage(Map<String, Import> calculatedImports, List<String> publicApiPackagesFromProvidedJars) {
+ if (bundleType != BundleType.USER) return;
+
+ List<String> nonPublicApiUsed = disallowedVespaImports(calculatedImports, publicApiPackagesFromProvidedJars);
+ if (! nonPublicApiUsed.isEmpty()) {
+ getLog().warn("This project uses packages that are not part of Vespa's public api: %s".formatted(nonPublicApiUsed));
+ }
+ }
+
private String wantedProvidedDependency() {
return switch (effectiveBundleType()) {
case CORE -> "jdisc_core";