diff options
author | gjoranv <gv@yahooinc.com> | 2023-05-19 17:21:04 +0200 |
---|---|---|
committer | gjoranv <gv@yahooinc.com> | 2023-05-23 01:34:20 +0200 |
commit | 8e40763559f4d32d51a65f5f53d8334299420969 (patch) | |
tree | ca863bb50931284c34107110258f9e5f26e94ce9 /bundle-plugin | |
parent | bebeaa9ef2df005a1abd088e0375c4dc869e2986 (diff) |
Process @PublicApi annotation and collect annotated packages.
Diffstat (limited to 'bundle-plugin')
6 files changed, 77 insertions, 33 deletions
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/AnalyzeClassVisitor.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/AnalyzeClassVisitor.java index 46a35b07ea7..e57af606b3a 100644 --- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/AnalyzeClassVisitor.java +++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/AnalyzeClassVisitor.java @@ -1,6 +1,7 @@ // 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.api.annotations.PublicApi; import com.yahoo.osgi.annotation.ExportPackage; import com.yahoo.osgi.annotation.Version; import org.apache.maven.artifact.versioning.ArtifactVersion; @@ -28,6 +29,7 @@ class AnalyzeClassVisitor extends ClassVisitor implements ImportCollector { private String name = null; private final Set<String> imports = new HashSet<>(); private Optional<ExportPackageAnnotation> exportPackageAnnotation = Optional.empty(); + private boolean isPublicApi = false; private final Optional<ArtifactVersion> defaultExportPackageVersion; @@ -159,6 +161,9 @@ class AnalyzeClassVisitor extends ClassVisitor implements ImportCollector { public AnnotationVisitor visitAnnotation(String desc, boolean visible) { if (ExportPackage.class.getName().equals(Type.getType(desc).getClassName())) { return visitExportPackage(); + } if (PublicApi.class.getName().equals(Type.getType(desc).getClassName())) { + isPublicApi = true; + return null; } else { if (visible) { addImportWithTypeDesc(desc); @@ -169,7 +174,8 @@ class AnalyzeClassVisitor extends ClassVisitor implements ImportCollector { ClassFileMetaData result() { assert (!imports.contains("int")); - return new ClassFileMetaData(name, imports, exportPackageAnnotation); + var packageInfo = new PackageInfo(Packages.packageName(name), exportPackageAnnotation, isPublicApi); + return new ClassFileMetaData(name, imports, packageInfo); } } diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/ClassFileMetaData.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/ClassFileMetaData.java index 5601430a27f..7e2f59c1e4d 100644 --- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/ClassFileMetaData.java +++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/ClassFileMetaData.java @@ -14,12 +14,12 @@ public class ClassFileMetaData { private final String name; private final Set<String> referencedClasses; - private final Optional<ExportPackageAnnotation> exportPackage; + private final PackageInfo packageInfo; - public ClassFileMetaData(String name, Set<String> referencedClasses, Optional<ExportPackageAnnotation> exportPackage) { + public ClassFileMetaData(String name, Set<String> referencedClasses, PackageInfo packageInfo) { this.name = name; this.referencedClasses = referencedClasses; - this.exportPackage = exportPackage; + this.packageInfo = packageInfo; } public String getName() { @@ -30,8 +30,16 @@ public class ClassFileMetaData { return referencedClasses; } + public PackageInfo packageInfo() { + return packageInfo; + } + public Optional<ExportPackageAnnotation> getExportPackage() { - return exportPackage; + return packageInfo.exportPackage(); + } + + public boolean isPublicApi() { + return packageInfo.isPublicApi(); } } diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/PackageInfo.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/PackageInfo.java new file mode 100644 index 00000000000..491f6d2a743 --- /dev/null +++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/PackageInfo.java @@ -0,0 +1,22 @@ +package com.yahoo.container.plugin.classanalysis; + +import java.util.Optional; + +/** + * The package + * + * @author gjoranv + */ +record PackageInfo(String name, Optional<ExportPackageAnnotation> exportPackage, boolean isPublicApi) { + + PackageInfo { + if (exportPackage.isEmpty() && isPublicApi) { + throw new IllegalArgumentException("Package %s is declared PublicApi, but is not exported.".formatted(name)); + } + } + + PackageInfo hasExportPackageOrElse(PackageInfo other) { + return exportPackage().isPresent() ? this : other; + } + +} diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/PackageTally.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/PackageTally.java index 03398307e03..6e8fc89c605 100644 --- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/PackageTally.java +++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/classanalysis/PackageTally.java @@ -17,16 +17,17 @@ import java.util.stream.Collectors; * @author ollivir */ public class PackageTally { - private final Map<String, Optional<ExportPackageAnnotation>> definedPackagesMap; + + private final Map<String, PackageInfo> definedPackages; private final Set<String> referencedPackagesUnfiltered; - PackageTally(Map<String, Optional<ExportPackageAnnotation>> definedPackagesMap, Set<String> referencedPackagesUnfiltered) { - this.definedPackagesMap = definedPackagesMap; + PackageTally(Map<String, PackageInfo> definedPackages, Set<String> referencedPackagesUnfiltered) { + this.definedPackages = definedPackages; this.referencedPackagesUnfiltered = referencedPackagesUnfiltered; } public Set<String> definedPackages() { - return definedPackagesMap.keySet(); + return definedPackages.keySet(); } public Set<String> referencedPackages() { @@ -35,8 +36,8 @@ public class PackageTally { public Map<String, ExportPackageAnnotation> exportedPackages() { Map<String, ExportPackageAnnotation> ret = new HashMap<>(); - definedPackagesMap.forEach((pkg, annotation) -> { - annotation.ifPresent(a -> ret.put(pkg, a)); + definedPackages.forEach((pkg, pkgInfo) -> { + pkgInfo.exportPackage().ifPresent(a -> ret.put(pkg, a)); }); return ret; } @@ -58,36 +59,37 @@ public class PackageTally { * Represents the classes for two package tallies that are deployed as a single unit. * <p> * ExportPackageAnnotations from this has precedence over the other. + * TODO: try using Map.merge (as in the functions below). Can't see how Maps.combine is any different. */ public PackageTally combine(PackageTally other) { - Map<String, Optional<ExportPackageAnnotation>> map = Maps.combine(this.definedPackagesMap, other.definedPackagesMap, - (l, r) -> l.isPresent() ? l : r); + var definedPkgs = Maps.combine(this.definedPackages, other.definedPackages, PackageInfo::hasExportPackageOrElse); Set<String> referencedPkgs = new HashSet<>(this.referencedPackagesUnfiltered); referencedPkgs.addAll(other.referencedPackagesUnfiltered); - return new PackageTally(map, referencedPkgs); + return new PackageTally(definedPkgs, referencedPkgs); } public static PackageTally combine(Collection<PackageTally> packageTallies) { - Map<String, Optional<ExportPackageAnnotation>> map = new HashMap<>(); + var definedPkgs = new HashMap<String, PackageInfo>(); Set<String> referencedPkgs = new HashSet<>(); - for (PackageTally pt : packageTallies) { - pt.definedPackagesMap.forEach((k, v) -> map.merge(k, v, (l, r) -> l.isPresent() ? l : r)); - referencedPkgs.addAll(pt.referencedPackagesUnfiltered); + for (PackageTally tally : packageTallies) { + tally.definedPackages.forEach((pkg, info) -> definedPkgs.merge(pkg, info, PackageInfo::hasExportPackageOrElse)); + referencedPkgs.addAll(tally.referencedPackagesUnfiltered); } - return new PackageTally(map, referencedPkgs); + return new PackageTally(definedPkgs, referencedPkgs); } public static PackageTally fromAnalyzedClassFiles(Collection<ClassFileMetaData> analyzedClassFiles) { - Map<String, Optional<ExportPackageAnnotation>> map = new HashMap<>(); - Set<String> referencedPkgs = new HashSet<>(); + var definedPkgs = new HashMap<String, PackageInfo>(); + var referencedPkgs = new HashSet<String>(); - for (ClassFileMetaData metaData : analyzedClassFiles) { - String packageName = Packages.packageName(metaData.getName()); - map.merge(packageName, metaData.getExportPackage(), (l, r) -> l.isPresent() ? l : r); - metaData.getReferencedClasses().forEach(className -> referencedPkgs.add(Packages.packageName(className))); + for (ClassFileMetaData classData : analyzedClassFiles) { + var pkgName = classData.packageInfo().name(); + definedPkgs.merge(pkgName, classData.packageInfo(), PackageInfo::hasExportPackageOrElse); + classData.getReferencedClasses().forEach(className -> referencedPkgs.add(Packages.packageName(className))); } - return new PackageTally(map, referencedPkgs); + return new PackageTally(definedPkgs, referencedPkgs); } + } diff --git a/bundle-plugin/src/test/java/com/yahoo/container/plugin/classanalysis/AnalyzeClassTest.java b/bundle-plugin/src/test/java/com/yahoo/container/plugin/classanalysis/AnalyzeClassTest.java index 9a7aade7ffb..11fe4a14d74 100644 --- a/bundle-plugin/src/test/java/com/yahoo/container/plugin/classanalysis/AnalyzeClassTest.java +++ b/bundle-plugin/src/test/java/com/yahoo/container/plugin/classanalysis/AnalyzeClassTest.java @@ -3,28 +3,27 @@ package com.yahoo.container.plugin.classanalysis; import com.yahoo.container.plugin.classanalysis.sampleclasses.Base; import com.yahoo.container.plugin.classanalysis.sampleclasses.ClassAnnotation; -import com.yahoo.container.plugin.classanalysis.sampleclasses.InvisibleAnnotation; import com.yahoo.container.plugin.classanalysis.sampleclasses.Derived; import com.yahoo.container.plugin.classanalysis.sampleclasses.DummyAnnotation; -import com.yahoo.container.plugin.classanalysis.sampleclasses.InvisibleDummyAnnotation; import com.yahoo.container.plugin.classanalysis.sampleclasses.Fields; import com.yahoo.container.plugin.classanalysis.sampleclasses.Interface1; import com.yahoo.container.plugin.classanalysis.sampleclasses.Interface2; -import com.yahoo.container.plugin.classanalysis.sampleclasses.RecordWithOverride; -import com.yahoo.container.plugin.classanalysis.sampleclasses.SwitchStatement; +import com.yahoo.container.plugin.classanalysis.sampleclasses.InvisibleAnnotation; +import com.yahoo.container.plugin.classanalysis.sampleclasses.InvisibleDummyAnnotation; import com.yahoo.container.plugin.classanalysis.sampleclasses.MethodAnnotation; import com.yahoo.container.plugin.classanalysis.sampleclasses.MethodInvocation; +import com.yahoo.container.plugin.classanalysis.sampleclasses.RecordWithOverride; +import com.yahoo.container.plugin.classanalysis.sampleclasses.SwitchStatement; import com.yahoo.osgi.annotation.ExportPackage; import com.yahoo.osgi.annotation.Version; import org.junit.jupiter.api.Test; import javax.security.auth.login.LoginException; -import java.awt.Image; +import java.awt.*; import java.awt.image.ImagingOpException; import java.awt.image.Kernel; import java.util.List; import java.util.Optional; -import java.util.Set; import static com.yahoo.container.plugin.classanalysis.TestUtilities.analyzeClass; import static com.yahoo.container.plugin.classanalysis.TestUtilities.classFile; @@ -133,7 +132,12 @@ public class AnalyzeClassTest { @Test void export_annotations_are_processed() { assertEquals(Optional.of(new ExportPackageAnnotation(3, 1, 4, "TEST_QUALIFIER-2")), - Analyze.analyzeClass(classFile("com.yahoo.container.plugin.classanalysis.sampleclasses.package-info")).getExportPackage()); + Analyze.analyzeClass(classFile("com.yahoo.container.plugin.classanalysis.sampleclasses.package-info")).getExportPackage()); + } + + @Test + void publicApi_annotations_are_processed() { + assertTrue(Analyze.analyzeClass(classFile("com.yahoo.container.plugin.classanalysis.sampleclasses.package-info")).isPublicApi()); } @Test diff --git a/bundle-plugin/src/test/java/com/yahoo/container/plugin/classanalysis/sampleclasses/package-info.java b/bundle-plugin/src/test/java/com/yahoo/container/plugin/classanalysis/sampleclasses/package-info.java index d0d1db97c26..5f69032db17 100644 --- a/bundle-plugin/src/test/java/com/yahoo/container/plugin/classanalysis/sampleclasses/package-info.java +++ b/bundle-plugin/src/test/java/com/yahoo/container/plugin/classanalysis/sampleclasses/package-info.java @@ -1,6 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. @ExportPackage(version = @Version(major = 3, minor = 1, micro = 4, qualifier = "TEST_QUALIFIER-2")) +@PublicApi package com.yahoo.container.plugin.classanalysis.sampleclasses; +import com.yahoo.api.annotations.PublicApi; import com.yahoo.osgi.annotation.ExportPackage; import com.yahoo.osgi.annotation.Version; |