summaryrefslogtreecommitdiffstats
path: root/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java
diff options
context:
space:
mode:
Diffstat (limited to 'bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java')
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java104
1 files changed, 88 insertions, 16 deletions
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 f5d3259c537..d217273e42b 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;
@@ -38,6 +40,14 @@ import static com.yahoo.container.plugin.util.Files.allDescendantFiles;
@Mojo(name = "generate-osgi-manifest", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true)
public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
+ private enum BundleType {
+ CORE, // up to container-dev
+ INTERNAL, // other vespa bundles (need not be set for groupId 'com.yahoo.vespa')
+ USER
+ }
+
+ private static final String VESPA_GROUP_ID = "com.yahoo.vespa";
+
@Parameter
private String discApplicationClass = null;
@@ -56,6 +66,19 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
@Parameter(alias = "Main-Class")
private String mainClass = null;
+ @Parameter(alias = "Bundle-Type")
+ private BundleType bundleType = BundleType.USER;
+
+ @Parameter(defaultValue = "false")
+ private boolean suppressWarningMissingImportPackages;
+ @Parameter(defaultValue = "false")
+ private boolean suppressWarningPublicApi;
+ @Parameter(defaultValue = "false")
+ private boolean suppressWarningOverlappingPackages;
+
+ @Parameter(defaultValue = "false")
+ private boolean failOnWarnings;
+
@Parameter(defaultValue = "false")
private boolean buildLegacyVespaPlatformBundle;
@@ -69,10 +92,12 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
if (! isContainerDiscArtifact(project.getArtifact()))
throwIfInternalContainerArtifactsAreIncluded(artifactSet.getJarArtifactsToInclude());
- List<Export> exportedPackagesFromProvidedJars = exportedPackagesAggregated(
- artifactSet.getJarArtifactsProvided().stream().map(Artifact::getFile).toList());
+ List<Artifact> providedJarArtifacts = artifactSet.getJarArtifactsProvided();
+ List<File> providedJarFiles = providedJarArtifacts.stream().map(Artifact::getFile).toList();
+ List<Export> exportedPackagesFromProvidedJars = exportedPackagesAggregated(providedJarFiles);
+ List<String> publicApiPackagesFromProvidedJars = publicApiPackagesAggregated(providedJarFiles);
- // Packages from Export-Package headers in provided scoped jars
+ // Packages from Export-Package/PublicApi headers in provided scoped jars
Set<String> exportedPackagesFromProvidedDeps = ExportPackages.packageNames(exportedPackagesFromProvidedJars);
// Packaged defined in this project's code
@@ -86,12 +111,12 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
logDebugPackageSets(exportedPackagesFromProvidedJars, includedPackages);
- if (hasJdiscCoreProvided(artifactSet.getJarArtifactsProvided())) {
+ if (hasJdiscCoreProvided(providedJarArtifacts)) {
// jdisc_core being provided guarantees that log output does not contain its exported packages
logMissingPackages(exportedPackagesFromProvidedDeps, projectPackages, compileJarsPackages, includedPackages);
- } else {
- getLog().warn("This project does not have jdisc_core as provided dependency, so the " +
- "generated 'Import-Package' OSGi header may be missing important packages.");
+ } else if (! suppressWarningMissingImportPackages) {
+ warnOrThrow(("This project does not have '%s' as provided dependency, so the generated 'Import-Package' " +
+ "OSGi header may be missing important packages.").formatted(wantedProvidedDependency()));
}
logOverlappingPackages(projectPackages, exportedPackagesFromProvidedDeps);
logUnnecessaryPackages(compileJarsPackages, exportedPackagesFromProvidedDeps);
@@ -100,9 +125,12 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
includedPackages.definedPackages(),
exportsByPackageName(exportedPackagesFromProvidedJars));
+ List<String> nonPublicApiUsed = disallowedVespaImports(calculatedImports, publicApiPackagesFromProvidedJars);
+ logNonPublicApiUsage(nonPublicApiUsed);
Map<String, String> manifestContent = generateManifestContent(artifactSet.getJarArtifactsToInclude(), calculatedImports, includedPackages);
- addAdditionalManifestProperties(manifestContent);
+ addAdditionalManifestProperties(manifestContent, includedPackages);
+ addManifestPropertiesForUserBundles(manifestContent, nonPublicApiUsed);
createManifestFile(Paths.get(project.getBuild().getOutputDirectory()), manifestContent);
} catch (Exception e) {
@@ -110,7 +138,21 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
}
}
- private void addAdditionalManifestProperties(Map<String, String> manifestContent) {
+ private String wantedProvidedDependency() {
+ return switch (effectiveBundleType()) {
+ case CORE -> "jdisc_core";
+ case INTERNAL -> "container-dev";
+ case USER -> "container";
+ };
+ }
+
+ private BundleType effectiveBundleType() {
+ if (bundleType != BundleType.USER) return bundleType;
+ return isVespaInternalGroupId(project.getGroupId()) ? BundleType.INTERNAL : BundleType.USER;
+ }
+
+ private void addAdditionalManifestProperties(Map<String, String> manifestContent, PackageTally includedPackages) {
+ addIfNotEmpty(manifestContent, "X-JDisc-PublicApi-Package", publicApi(includedPackages));
addIfNotEmpty(manifestContent, "Bundle-Activator", bundleActivator);
addIfNotEmpty(manifestContent, "X-JDisc-Privileged-Activator", jdiscPrivilegedActivator);
addIfNotEmpty(manifestContent, "Main-Class", mainClass);
@@ -119,6 +161,20 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
addIfNotEmpty(manifestContent, "WebInfUrl", webInfUrl);
}
+ private void addManifestPropertiesForUserBundles(Map<String, String> manifestContent, List<String> nonPublicApiUsed) {
+ if (effectiveBundleType() != BundleType.USER) return;
+ addIfNotEmpty(manifestContent, "X-JDisc-Non-PublicApi-Import-Package", String.join(",", nonPublicApiUsed));
+ }
+
+ private void logNonPublicApiUsage(List<String> nonPublicApiUsed) {
+ if (suppressWarningPublicApi || effectiveBundleType() != BundleType.USER || nonPublicApiUsed.isEmpty()) return;
+ warnOrThrow("This project uses packages that are not part of Vespa's public api: %s".formatted(nonPublicApiUsed));
+ }
+
+ private static String publicApi(PackageTally tally) {
+ return tally.publicApiPackages().stream().sorted().collect(Collectors.joining(","));
+ }
+
private void logDebugPackageSets(List<Export> exportedPackagesFromProvidedJars, PackageTally includedPackages) {
if (getLog().isDebugEnabled()) {
getLog().debug("Referenced packages = " + includedPackages.referencedPackages());
@@ -154,10 +210,12 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
private void logOverlappingPackages(PackageTally projectPackages,
Set<String> exportedPackagesFromProvidedDeps) {
+ if (suppressWarningOverlappingPackages) return;
+
Set<String> overlappingProjectPackages = Sets.intersection(projectPackages.definedPackages(), exportedPackagesFromProvidedDeps);
if (! overlappingProjectPackages.isEmpty()) {
- getLog().warn("This project defines packages that are also defined in provided scoped dependencies " +
- "(overlapping packages are strongly discouraged): " + overlappingProjectPackages);
+ warnOrThrow("This project defines packages that are also defined in provided scoped dependencies " +
+ "(overlapping packages are strongly discouraged): " + overlappingProjectPackages);
}
}
@@ -184,9 +242,8 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
List<Artifact> unsupportedArtifacts = nonJarArtifacts.stream().filter(a -> ! a.getType().equals("pom"))
.toList();
- unsupportedArtifacts.forEach(artifact -> getLog()
- .warn(String.format("Unsupported artifact '%s': Type '%s' is not supported. Please file a feature request.",
- artifact.getId(), artifact.getType())));
+ unsupportedArtifacts.forEach(artifact -> warnOrThrow(String.format("Unsupported artifact '%s': Type '%s' is not supported. Please file a feature request.",
+ artifact.getId(), artifact.getType())));
}
private void throwIfInternalContainerArtifactsAreIncluded(Collection<Artifact> includedArtifacts) throws MojoExecutionException {
@@ -201,12 +258,18 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
}
}
+ private boolean isVespaInternalGroupId(String groupId) {
+ return groupId.equals(VESPA_GROUP_ID)
+ || groupId.equals(VESPA_GROUP_ID + ".hosted")
+ || groupId.equals(VESPA_GROUP_ID + ".hosted.controller");
+ }
+
private boolean isJdiscComponentArtifact(Artifact a) {
- return a.getArtifactId().equals("component") && a.getGroupId().equals("com.yahoo.vespa");
+ return a.getArtifactId().equals("component") && a.getGroupId().equals(VESPA_GROUP_ID);
}
private boolean isContainerDiscArtifact(Artifact a) {
- return a.getArtifactId().equals("container-disc") && a.getGroupId().equals("com.yahoo.vespa");
+ return a.getArtifactId().equals("container-disc") && a.getGroupId().equals(VESPA_GROUP_ID);
}
private PackageTally getProjectClassesTally() {
@@ -219,4 +282,13 @@ public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
return PackageTally.fromAnalyzedClassFiles(analyzedClasses);
}
+
+ private void warnOrThrow(String... messages){
+ String message = String.join("\n", messages);
+ if (failOnWarnings) {
+ throw new RuntimeException(message);
+ }
+ getLog().warn(message);
+ }
+
}