This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-providertype-bnd-plugin.git


The following commit(s) were added to refs/heads/master by this push:
     new 490b515  SLING-12181 Evaluate provider type from annotations
490b515 is described below

commit 490b5151d95e6f55559909a67614e038bfaf9a64
Author: Konrad Windszus <[email protected]>
AuthorDate: Tue Dec 5 21:08:41 2023 +0100

    SLING-12181 Evaluate provider type from annotations
    
    Only in case META-INF/api-info.json is not available in the class path
    (no apis-jar) and if enabled via attribute
---
 pom.xml                                            |  34 ++++++-
 readme.md                                          |  20 +++-
 .../bndplugin/ProviderTypeScanner.java             | 109 ++++++++++++++++-----
 .../bndplugin/BndBuilderExtension.java             |  38 ++++---
 .../providertype/bndplugin/MyBinaryDownload.java   |  62 ++++++++++++
 .../bndplugin/ProviderTypeScannerTest.java         |  28 +++---
 6 files changed, 234 insertions(+), 57 deletions(-)

diff --git a/pom.xml b/pom.xml
index 0ae2e95..0a717a6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,7 +44,33 @@
         
<url>https://github.com/apache/sling-org-apache-sling-providertype-bnd-plugin/tree/${project.scm.tag}</url>
         <tag>HEAD</tag>
     </scm>
-  
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                  <execution>
+                    <id>copy-dependencies</id>
+                    <phase>generate-test-resources</phase>
+                    <goals>
+                      <goal>copy-dependencies</goal>
+                    </goals>
+                    <configuration>
+                      
<outputDirectory>${project.build.directory}/test-classpath</outputDirectory>
+                      <overWriteReleases>false</overWriteReleases>
+                      <overWriteSnapshots>false</overWriteSnapshots>
+                      <overWriteIfNewer>true</overWriteIfNewer>
+                      
<includeArtifactIds>oak-jackrabbit-api</includeArtifactIds>
+                      <stripVersion>true</stripVersion>
+                    </configuration>
+                  </execution>
+                </executions>
+              </plugin>
+        </plugins>
+    </build>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
@@ -87,5 +113,11 @@
             <artifactId>slf4j-simple</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>oak-jackrabbit-api</artifactId>
+            <version>1.58.0</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/readme.md b/readme.md
index ef277d8..b1af77e 100644
--- a/readme.md
+++ b/readme.md
@@ -14,7 +14,7 @@ This module contains a [Bnd plugin][bnd-plugins] enforcing 
that no class of the
 
 That ensures that the `import-package` version ranges are not narrow but 
[broad][semantic-versioning] and the risk that the bundle is incompatible with 
newer versions of its dependent bundles is less likely.
 
-# Usage
+## Usage
 
 For usage with Maven the Bnd plugin has to be added to the plugin dependencies 
of `bnd-maven-plugin` (or `maven-bundle-plugin`) like this:
 
@@ -39,7 +39,7 @@ In addition the `bnd.bnd` file needs to register the Bnd 
plugin with the [plugin
 
-plugin.providertype:org.apache.sling.providertype.bndplugin.ProviderTypeScanner
 ```
 
-## Configuration
+### Configuration
 
 To explicitly ignore certain provider types (i.e. don't fail when these are 
extended/implemented) one can use the attribute `ignored` with one or multiple 
comma-separated fully qualified provider type names. For example
 
@@ -47,18 +47,28 @@ To explicitly ignore certain provider types (i.e. don't 
fail when these are exte
 
-plugin.providertype:org.apache.sling.providertype.bndplugin.ProviderTypeScanner;ignored=org.apache.jackrabbit.api.security.user.User
 ```
 
-## Prerequisites
+In case the provider types are not provided in a classpath resource named 
[`META-INF/api-info.json`][api-info.json] the plugin can optionally evaluate 
the classpath for the relevant annotations directly. Since this is time 
consuming it needs to be explicitly enabled via attribute `evaluateAnnotations` 
with value `true`.
+
+```
+-plugin.providertype:org.apache.sling.providertype.bndplugin.ProviderTypeScanner;evaluateAnnotations=true
+```
+
+Multiple attributes must be separated with `;` according to [OSGi Common 
Header Syntax][common-header].
+
+### Prerequisites
 
 * Bnd 6.0 or newer (integrated in `bnd-maven-plugin` version 6.0.0+ or 
`maven-bundle-plugin` version 5.1.5+)
 * Java 11 or newer
 
-# Provider Type Information
+## Provider Type Information
 
 The information whether a type (i.e. a class or interface) is designed to be 
extended/implemented only by providers or also by consumers is determined 
originally from the the annotations 
[`@org.osgi.annotation.versioning.ProviderType`][provider-type] or 
[`@org.osgi.annotation.versioning.ConsumerType`][consumer-type].
-In order to speed up the check [the annotation is evaluated and extracted into 
a dedicated JSON file named `META-INF/api-info.json` when generating the apis 
jar](https://issues.apache.org/jira/browse/SLING-12135) and being looked up 
from there within this plugin.
+In order to speed up the check [the annotation is evaluated and extracted into 
a dedicated JSON file named `META-INF/api-info.json` when generating the apis 
jar][api-info.json] and being looked up from there within this plugin. Only as 
fallback and on demand this plugin evaluates the annotations from the classpath 
directly.
 
 
 [bnd-plugins]: https://bnd.bndtools.org/chapters/870-plugins.html
 [provider-type]: 
https://docs.osgi.org/javadoc/osgi.annotation/8.0.0/org/osgi/annotation/versioning/ProviderType.html
 [consumer-type]: 
https://docs.osgi.org/javadoc/osgi.annotation/8.0.0/org/osgi/annotation/versioning/ConsumerType.html
 [semantic-versioning]: 
https://docs.osgi.org/whitepaper/semantic-versioning/060-importer-policy.html
+[api-info.json]: https://issues.apache.org/jira/browse/SLING-12135
+[common-header]: 
https://docs.osgi.org/specification/osgi.core/8.0.0/framework.module.html#framework.common.header.syntax
diff --git 
a/src/main/java/org/apache/sling/providertype/bndplugin/ProviderTypeScanner.java
 
b/src/main/java/org/apache/sling/providertype/bndplugin/ProviderTypeScanner.java
index d4c3b0a..84b814a 100644
--- 
a/src/main/java/org/apache/sling/providertype/bndplugin/ProviderTypeScanner.java
+++ 
b/src/main/java/org/apache/sling/providertype/bndplugin/ProviderTypeScanner.java
@@ -29,9 +29,11 @@ import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import aQute.bnd.build.Classpath.ClassVisitor;
 import aQute.bnd.osgi.Analyzer;
 import aQute.bnd.osgi.Clazz;
 import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.bnd.osgi.Jar;
 import aQute.bnd.osgi.Resource;
 import aQute.bnd.service.AnalyzerPlugin;
 import aQute.bnd.service.Plugin;
@@ -39,19 +41,19 @@ import aQute.lib.json.Decoder;
 import aQute.lib.json.JSONCodec;
 import aQute.service.reporter.Reporter;
 
-/**
- * Enforces that no classes implement or extend a type marked as provider.
- * Provider types are retrieved from the resource "META-INF/api-info.json" 
which is expected to be provided
- * in the class path.
- */
+/** Enforces that no classes implement or extend a type marked as provider. 
Provider types are retrieved from the resource
+ * "META-INF/api-info.json" which is expected to be provided in the class 
path. */
 public class ProviderTypeScanner implements AnalyzerPlugin, Plugin {
 
     private static final String API_INFO_JSON_RESOURCE_PATH = 
"META-INF/api-info.json";
     private static final String FIELD_PROVIDER_TYPES = "providerTypes";
     private static final String MESSAGE = "Type \"%s\" %s provider type 
\"%s\". This is not allowed!";
     private static final String ATTRIBUTE_IGNORED_PROVIDER_TYPES = "ignored";
+    private static final String ATTRIBUTE_EVALUATE_ANNOTATIONS_IN_CLASSPATH = 
"evaluateAnnotations";
+    
+    private static final List<String> PROVIDER_TYPE_ANNOTATION_FQNS = 
List.of("org.osgi.annotation.versioning.ProviderType", 
"aQute.bnd.annotation.ProviderType");
 
-    private Map<String,String> parameters = new HashMap<>();
+    private Map<String, String> parameters = new HashMap<>();
 
     @Override
     public void setProperties(Map<String, String> map) throws Exception {
@@ -67,28 +69,42 @@ public class ProviderTypeScanner implements AnalyzerPlugin, 
Plugin {
 
     @Override
     public boolean analyzeJar(Analyzer analyzer) throws Exception {
-        List<Resource> apiInfoJsonResources = analyzer.findResources(s -> 
s.equals(API_INFO_JSON_RESOURCE_PATH)).collect(Collectors.toList());
-        if(apiInfoJsonResources.isEmpty()) {
-            analyzer.warning("Could not find resource \"%s\" in the 
classpath", API_INFO_JSON_RESOURCE_PATH);
+        List<Resource> apiInfoJsonResources = analyzer.findResources(s -> 
s.equals(API_INFO_JSON_RESOURCE_PATH))
+                .collect(Collectors.toList());
+        final Set<String> providerTypes = new HashSet<>(); // This may contain 
fully qualified class names or package names
+        if (apiInfoJsonResources.isEmpty()) {
+            if 
(Boolean.parseBoolean(parameters.get(ATTRIBUTE_EVALUATE_ANNOTATIONS_IN_CLASSPATH)))
 {
+                analyzer.warning("Retrieving provider type info from 
annotations found in classpath...");
+                
providerTypes.addAll(collectProviderTypesFromClasspath(analyzer));
+            } else {
+                analyzer.warning("Could not find resource \"%s\" in the 
classpath", API_INFO_JSON_RESOURCE_PATH);
+            }
         } else {
-            Set<String> providerTypes = new HashSet<>();
             for (Resource apiInfoJsonResource : apiInfoJsonResources) {
                 try {
-                    Set<String> resourceProviderTypes = 
collectProviderTypes(analyzer, apiInfoJsonResource);
-                    analyzer.trace("Added provider types from resource \"%s\": 
%s", apiInfoJsonResource, String.join(",", resourceProviderTypes));
+                    Set<String> resourceProviderTypes = 
collectProviderTypesFromApiInfo(analyzer, apiInfoJsonResource);
+                    analyzer.trace("Added provider types from resource \"%s\": 
%s", apiInfoJsonResource,
+                            String.join(",", resourceProviderTypes));
                     providerTypes.addAll(resourceProviderTypes);
                 } catch (Exception e) {
                     throw new IllegalStateException("Could not parse JSON from 
resource " + apiInfoJsonResource, e);
                 }
             }
+        }
+        if (providerTypes.isEmpty()) {
+            analyzer.warning("No provider types found, skip checking bundle's 
classes");
+        } else {
             // remove ignored provider types
-            
Arrays.stream(parameters.getOrDefault(ATTRIBUTE_IGNORED_PROVIDER_TYPES, 
"").split(",")).filter(s -> !s.isBlank()).forEach(ignored -> {
-                if (providerTypes.remove(ignored)) {
-                    analyzer.trace("Ignore extensions of provider type \"%s\" 
due to plugin configuration", ignored);
-                } else {
-                    analyzer.warning("Ignored class \"%s\" is not defined as 
provider type at all, you can safely remove the according plugin parameter", 
ignored);
-                }
-            });
+            
Arrays.stream(parameters.getOrDefault(ATTRIBUTE_IGNORED_PROVIDER_TYPES, 
"").split(",")).filter(s -> !s.isBlank())
+                    .forEach(ignored -> {
+                        if (providerTypes.remove(ignored)) {
+                            analyzer.trace("Ignore extensions of provider type 
\"%s\" due to plugin configuration", ignored);
+                        } else {
+                            analyzer.warning(
+                                    "Ignored class \"%s\" is not defined as 
provider type at all, you can safely remove the according plugin parameter",
+                                    ignored);
+                        }
+                    });
             checkIfExtendingType(analyzer, analyzer.getClassspace().values(), 
providerTypes);
         }
         return false;
@@ -96,35 +112,78 @@ public class ProviderTypeScanner implements 
AnalyzerPlugin, Plugin {
 
     private void checkIfExtendingType(Reporter reporter, Collection<Clazz> 
clazzes, Set<String> providerTypes) {
         for (Clazz clazz : clazzes) {
-            if (clazz.getSuper() != null &&  
(providerTypes.contains(clazz.getSuper().getFQN()))) {
+            if (clazz.getSuper() != null && (isProvider(clazz.getSuper(), 
providerTypes))) {
                 reporter.error(MESSAGE, clazz.getFQN(), "extends", 
clazz.getSuper().getFQN()).file(clazz.getSourceFile());
             }
             for (TypeRef interfaceType : clazz.interfaces()) {
-                if (providerTypes.contains(interfaceType.getFQN())) {
+                if (isProvider(interfaceType, providerTypes)) {
                     reporter.error(MESSAGE, clazz.getFQN(), "implements", 
interfaceType.getFQN()).file(clazz.getSourceFile());
                 }
             }
         }
     }
 
+    static boolean isProvider(TypeRef type, Set<String> providerTypes) {
+        return providerTypes.stream().anyMatch(providerType -> 
providerType.equals(type.getFQN()) || 
providerType.equals(type.getPackageRef().getFQN()));
+    }
+
     @SuppressWarnings("unchecked")
-    private Set<String> collectProviderTypes(Reporter reporter, Resource 
apiInfoResource) throws Exception {
+    private Set<String> collectProviderTypesFromApiInfo(Reporter reporter, 
Resource apiInfoResource) throws Exception {
         JSONCodec codec = new JSONCodec();
         // read JSON file
         try (InputStream input = apiInfoResource.openInputStream();
-            Decoder decoder = codec.dec().from(input)) {
+                Decoder decoder = codec.dec().from(input)) {
             Map<?, ?> jsonMap = decoder.get(Map.class);
             Object providerTypes = jsonMap.get(FIELD_PROVIDER_TYPES);
             if (providerTypes == null) {
                 reporter.error("Resource \"%s\" does not contain a field named 
\"%s\"", API_INFO_JSON_RESOURCE_PATH, FIELD_PROVIDER_TYPES);
             } else if (!(providerTypes instanceof Collection)) {
-                reporter.error("Field \"%s\" in JSON resource \"%s\" is not 
containing a string array but a type converted to %s", FIELD_PROVIDER_TYPES, 
API_INFO_JSON_RESOURCE_PATH, providerTypes.getClass().getName());
+                reporter.error("Field \"%s\" in JSON resource \"%s\" is not 
containing a string array but a type converted to %s",
+                        FIELD_PROVIDER_TYPES, API_INFO_JSON_RESOURCE_PATH, 
providerTypes.getClass().getName());
             } else {
-                return new HashSet<>((Collection<String>)providerTypes);
+                return new HashSet<>((Collection<String>) providerTypes);
             }
         }
         return Collections.emptySet();
     }
 
+    private Set<String> collectProviderTypesFromClasspath(Analyzer analyzer) 
throws Exception {
+        // unfortunately bnd does not cache this information in an accessible 
way
+        ProviderTypeCollectorClassVisitor visitor = new 
ProviderTypeCollectorClassVisitor();
+        visit(visitor, analyzer);
+        return visitor.getProviderTypes();
+    }
 
+    /** Visit each class on the class path (includes package-info.class).
+     *
+     * @param visitor the visitor */
+    private void visit(ClassVisitor visitor, Analyzer analyzer) throws 
Exception {
+        for (Jar classpathJar : analyzer.getClasspath()) {
+            for (String path : classpathJar.getResources().keySet()) {
+                if (path.endsWith(".class")) {
+                    Resource r = classpathJar.getResource(path);
+                    Clazz c = new Clazz(analyzer, path, r);
+                    c.parseClassFile();
+                    visitor.visit(c);
+                }
+            }
+        }
+    }
+
+    private static final class ProviderTypeCollectorClassVisitor implements 
ClassVisitor {
+
+        final Set<String> providerTypes = new HashSet<>();
+
+        @Override
+        public boolean visit(Clazz clazz) throws Exception {
+            if (clazz.annotations().stream().anyMatch(at -> 
PROVIDER_TYPE_ANNOTATION_FQNS.contains(at.getFQN()))) {
+                providerTypes.add(clazz.getFQN());
+            }
+            return true;
+        }
+
+        public Set<String> getProviderTypes() {
+            return providerTypes;
+        }
+    }
 }
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/providertype/bndplugin/BndBuilderExtension.java
 
b/src/test/java/org/apache/sling/providertype/bndplugin/BndBuilderExtension.java
index d14add8..3e662f2 100644
--- 
a/src/test/java/org/apache/sling/providertype/bndplugin/BndBuilderExtension.java
+++ 
b/src/test/java/org/apache/sling/providertype/bndplugin/BndBuilderExtension.java
@@ -20,9 +20,8 @@ package org.apache.sling.providertype.bndplugin;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
+import java.util.Map;
 import java.util.jar.Manifest;
 
 import org.junit.jupiter.api.extension.AfterEachCallback;
@@ -35,11 +34,11 @@ import aQute.bnd.service.Plugin;
 
 public class BndBuilderExtension implements BeforeEachCallback, 
AfterEachCallback {
     
-    protected Builder builder;
-    private final Collection<Object> plugins;
+    private Builder builder;
+    private final Object plugin;
 
-    public BndBuilderExtension(Object... plugins) {
-        this.plugins = Arrays.asList(plugins);
+    public BndBuilderExtension(Object plugin) {
+        this.plugin = plugin;
     }
 
     @Override
@@ -49,13 +48,24 @@ public class BndBuilderExtension implements 
BeforeEachCallback, AfterEachCallbac
         classesDirJar.setManifest(new Manifest());
         builder.setJar(classesDirJar); // jar closed with builder
         builder.setSourcepath(new File[] { new File("src/test/java") } );
-        for (Object plugin : plugins) {
-            if (plugin instanceof Plugin) {
-                Plugin pluginPlugin = (Plugin)plugin;
-                pluginPlugin.setReporter(builder);
-                pluginPlugin.setProperties(new HashMap<>()); // not used
-            }
-            builder.addBasicPlugin(plugin);
+        if (plugin instanceof Plugin) {
+            Plugin pluginPlugin = (Plugin)plugin;
+            pluginPlugin.setReporter(builder);
+            pluginPlugin.setProperties(Collections.emptyMap());
+        }
+        builder.addBasicPlugin(plugin);
+    }
+
+    protected Builder getBuilder() {
+        return builder;
+    }
+
+    protected void setPluginProperties(Map<String, String> pluginProperties) 
throws Exception{
+        if (plugin instanceof Plugin) {
+            Plugin pluginPlugin = (Plugin)plugin;
+            pluginPlugin.setProperties(pluginProperties);
+        } else {
+            throw new IllegalStateException("Given plugin does not implement 
class Plugin but is " + plugin);
         }
     }
 
diff --git 
a/src/test/java/org/apache/sling/providertype/bndplugin/MyBinaryDownload.java 
b/src/test/java/org/apache/sling/providertype/bndplugin/MyBinaryDownload.java
new file mode 100644
index 0000000..13ebaca
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/providertype/bndplugin/MyBinaryDownload.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.providertype.bndplugin;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.binary.BinaryDownload;
+import org.apache.jackrabbit.api.binary.BinaryDownloadOptions;
+
+public class MyBinaryDownload implements BinaryDownload {
+
+    @Override
+    public InputStream getStream() throws RepositoryException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int read(byte[] b, long position) throws IOException, 
RepositoryException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public long getSize() throws RepositoryException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void dispose() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public URI getURI(BinaryDownloadOptions downloadOptions) throws 
RepositoryException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git 
a/src/test/java/org/apache/sling/providertype/bndplugin/ProviderTypeScannerTest.java
 
b/src/test/java/org/apache/sling/providertype/bndplugin/ProviderTypeScannerTest.java
index bf26f0f..fa41758 100644
--- 
a/src/test/java/org/apache/sling/providertype/bndplugin/ProviderTypeScannerTest.java
+++ 
b/src/test/java/org/apache/sling/providertype/bndplugin/ProviderTypeScannerTest.java
@@ -25,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.fail;
 import java.io.File;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
@@ -38,8 +39,8 @@ class ProviderTypeScannerTest {
     static BndBuilderExtension bndBuilderExtension = new 
BndBuilderExtension(new ProviderTypeScanner());
 
     @Test
-    void testBuildWithViolations() throws Exception {
-        Builder builder = bndBuilderExtension.builder;
+    void testBuildWithViolationsAndApiInfoJson() throws Exception {
+        Builder builder = bndBuilderExtension.getBuilder();
         // add classpath entry with api-info.json
         builder.setClasspath(new File[] { new File("src/test/resources") });
         try (Jar jar = builder.build()) {
@@ -55,35 +56,38 @@ class ProviderTypeScannerTest {
 
     @Test
     void testBuildWithoutProviderTypeMetadata() throws Exception {
-        Builder builder = bndBuilderExtension.builder;
+        Builder builder = bndBuilderExtension.getBuilder();
+        // add classpath entry without api-info.json
+        builder.setClasspath(new File[] { new 
File("target/test-classpath/oak-jackrabbit-api.jar") });
+        bndBuilderExtension.setPluginProperties(Map.of("evaluateAnnotations", 
"true"));
         try (Jar jar = builder.build()) {
-            if (!builder.getErrors().isEmpty()) {
-                fail(String.join("\n", builder.getErrors()));
-            }
+            List<String> expectedErrors = Arrays.asList(
+                    "Type 
\"org.apache.sling.providertype.bndplugin.MyBinaryDownload\" implements 
provider type \"org.apache.jackrabbit.api.binary.BinaryDownload\". This is not 
allowed!");
+            assertEquals(expectedErrors, builder.getErrors());
             List<String> expectedWarnings = Arrays.asList(
-                    "Could not find resource \"META-INF/api-info.json\" in the 
classpath");
+                    "Retrieving provider type info from annotations found in 
classpath...");
             assertEquals(expectedWarnings, builder.getWarnings());
         }
     }
 
     @Test
     void testBuildWithInvalidProviderTypeMetadata() throws Exception {
-        Builder builder = bndBuilderExtension.builder;
+        Builder builder = bndBuilderExtension.getBuilder();
         // add classpath entry with api-info.json
         builder.setClasspath(new File[] { new File("src/test/resources2") });
         try (Jar jar = builder.build()) {
             List<String> expectedErrors = Arrays.asList(
                     "Resource \"META-INF/api-info.json\" does not contain a 
field named \"providerTypes\"");
             assertEquals(expectedErrors, builder.getErrors());
-            if (!builder.getWarnings().isEmpty()) {
-                fail(String.join("\n", builder.getWarnings()));
-            }
+            List<String> expectedWarnings = Arrays.asList(
+                    "No provider types found, skip checking bundle's classes");
+            assertEquals(expectedWarnings, builder.getWarnings());
         }
     }
 
     @Test
     void testBuildWithInvalidProviderTypeMetadata2() throws Exception {
-        Builder builder = bndBuilderExtension.builder;
+        Builder builder = bndBuilderExtension.getBuilder();
         // add classpath entry with api-info.json
         builder.setClasspath(new File[] { new File("src/test/resources3") });
         try (Jar jar = builder.build()) {

Reply via email to