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

cziegeler pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git


The following commit(s) were added to refs/heads/master by this push:
     new 3b59023  SLING-10264 : Allow to add additional artifacts for javadoc 
generation
3b59023 is described below

commit 3b590238b26ced225d8112e9c8b1624921aacc24
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Mon Mar 29 14:15:16 2021 +0200

    SLING-10264 : Allow to add additional artifacts for javadoc generation
---
 pom.xml                                            |   2 +-
 .../sling/feature/maven/mojos/ApisJarMojo.java     | 224 ++++++++++++---------
 .../maven/mojos/apis/ApisConfiguration.java        |  55 ++++-
 .../feature/maven/mojos/apis/ApisJarContext.java   |   9 +
 .../sling/feature/maven/mojos/apis/ApisUtil.java   |  82 ++++++++
 .../feature/maven/mojos/apis/RegionSupport.java    |  33 ++-
 6 files changed, 301 insertions(+), 104 deletions(-)

diff --git a/pom.xml b/pom.xml
index dad3b43..b7d5c2e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
     </parent>
 
     <artifactId>slingfeature-maven-plugin</artifactId>
-    <version>1.4.25-SNAPSHOT</version>
+    <version>1.5.0-SNAPSHOT</version>
     <packaging>maven-plugin</packaging>
 
     <name>Apache Sling OSGi Feature Maven Plugin</name>
diff --git 
a/src/main/java/org/apache/sling/feature/maven/mojos/ApisJarMojo.java 
b/src/main/java/org/apache/sling/feature/maven/mojos/ApisJarMojo.java
index 4b292dc..cc6c345 100644
--- a/src/main/java/org/apache/sling/feature/maven/mojos/ApisJarMojo.java
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/ApisJarMojo.java
@@ -30,11 +30,12 @@ import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
-import java.util.TreeSet;
 import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
@@ -379,6 +380,18 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
     @Parameter(property = "enabled.toggles")
     private String enabledToggles;
 
+    /**
+     * A list of configurations to add additional artifacts to a region
+     * for javadoc generation. The value is a comma separated list of 
extension names
+     * from the feature model. If such an extension exists, it must be of type 
artifacts.
+     * The list of names can be prefixed with a region name separated by a 
colon from
+     * the list of names. In that case, the artifacts are only added to that 
region.
+     *
+     * @since 1.5.0
+     */
+    @Parameter
+    private List<String> javadocAdditionalExtensions;
+
     @Parameter(defaultValue = "${project.build.directory}/apis-jars", readonly 
= true)
     private File mainOutputDir;
 
@@ -453,9 +466,24 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
         ctx.getConfig().setManifestEntries(manifestProperties);
         ctx.getConfig().logConfiguration(getLog());
         ctx.getConfig().setEnabledToggles(this.enabledToggles);
+        
ctx.getConfig().setAdditionalJavadocExtensions(this.javadocAdditionalExtensions);
 
         ctx.setDependencyRepositories(this.apiRepositoryUrls);
 
+        // check additional extension configuration first to fail fast
+        if ( this.generateJavadocJar ) {
+            for (final ApiRegion apiRegion : regions.listRegions()) {
+                final String regionName = apiRegion.getName();
+
+                final List<Artifact> artifacts = 
ApisUtil.getAdditionalJavadocArtifacts(ctx, regionName);
+                for(final Artifact artifact : artifacts ) {
+                    if ( 
ctx.getFeature().getBundles().getExact(artifact.getId() ) != null ) {
+                        throw new MojoExecutionException("Additional javadoc 
artifact is also listed as a bundle " + artifact.getId().toMvnId());
+                    }
+                }
+            }
+        }
+
         // for each bundle included in the feature file and record directories
         for (final Artifact artifact : feature.getBundles()) {
             onArtifact(regions, ctx, regionSupport, artifact);
@@ -513,7 +541,7 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
                 links.calculateLinks(ctx.getConfig().getJavadocLinks(), 
ctx.getArtifactInfos(regionName, false),
                         ext != null ? ext.getFramework() : null);
 
-                final Collection<ArtifactInfo> infos = generateJavadoc(ctx, 
regionName, links, javadocsDir);
+                final Collection<ArtifactInfo> infos = generateJavadoc(ctx, 
regionName, links, javadocsDir, regionSupport);
                 if (infos != null) {
                     ctx.setJavadocDir(javadocsDir);
                     final File javadocJar = createArchive(ctx, apiRegion, 
ArtifactType.JAVADOC,
@@ -553,7 +581,7 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
     private void report(final ApisJarContext ctx, final File jarFile, final 
ArtifactType artifactType,
             final ApiRegion apiRegion, final boolean omitDependencyArtifacts, 
final List<String> report,
             final JavadocLinks links) throws MojoExecutionException {
-        final Map.Entry<Set<String>, Set<String>> packageResult = 
getPackages(ctx, jarFile,
+        final Map.Entry<Set<String>, Set<String>> packageResult = 
ApisUtil.getPackages(ctx, jarFile,
                 artifactType.getContentExtension());
         final Set<String> apiPackages = packageResult.getKey();
         final Set<String> otherPackages = packageResult.getValue();
@@ -590,6 +618,18 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
         }
         if (artifactType == ArtifactType.JAVADOC) {
             otherPackages.removeAll(ctx.getPackagesWithoutSources());
+            // handle additional artifacts
+            for(final Artifact artifact : 
ApisUtil.getAdditionalJavadocArtifacts(ctx, apiRegion.getName()) ) {
+                final ArtifactInfo info = 
ctx.getArtifactInfo(artifact.getId());
+                if ( info != null ) {
+                    for(final Clause clause : 
info.getUsedExportedPackages(apiRegion.getName())) {
+                        if ( !apiPackages.remove(clause.getName()) ) {
+                            final ApiExport export = new 
ApiExport(clause.getName());
+                            missing.add(export);
+                        }
+                    }
+                }
+            }
         }
         otherPackages.removeAll(ctx.getPackagesWithoutJavaClasses());
 
@@ -621,7 +661,7 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
                         .concat(String.join(",", candidates)));
             }
             for (final String m : apiPackages) {
-                report.add("- Wrong package ".concat(m));
+                report.add("- Unwanted package ".concat(m));
             }
         }
     }
@@ -678,9 +718,9 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
      * @param artifact The artifact
      * @throws MojoExecutionException
      */
-    private void onArtifact(final ApiRegions apiRegions, 
+    private void onArtifact(final ApiRegions apiRegions,
             final ApisJarContext ctx,
-            final RegionSupport regionSupport, 
+            final RegionSupport regionSupport,
             Artifact artifact) throws MojoExecutionException {
         final File bundleFile = getArtifactFile(artifact.getId());
 
@@ -1390,53 +1430,55 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
              final JarArchiver jarArchiver,
              final List<Source> sources) {
         for (final ArtifactInfo info : infos) {
-            final int prefixLength = 
info.getBinDirectory().getAbsolutePath().length() + 1;
-            for (final File resource : info.getIncludedResources()) {
-                final String name = 
resource.getAbsolutePath().substring(prefixLength);
-                getLog().debug("Adding resource " + name);
+            if ( info.getBinDirectory() != null ) {
+                final int prefixLength = 
info.getBinDirectory().getAbsolutePath().length() + 1;
+                for (final File resource : info.getIncludedResources()) {
+                    final String name = 
resource.getAbsolutePath().substring(prefixLength);
+                    getLog().debug("Adding resource " + name);
 
-                if ( jarArchiver != null ) {
-                    jarArchiver.addFile(resource, name);
+                    if ( jarArchiver != null ) {
+                        jarArchiver.addFile(resource, name);
 
-                }
-                if ( sources != null ) {
-                    sources.add(new FileSource(info.getBinDirectory(), 
resource));
+                    }
+                    if ( sources != null ) {
+                        sources.add(new FileSource(info.getBinDirectory(), 
resource));
+                    }
                 }
             }
         }
 
-       // add additional resources
-       if (resources != null) {
-        for (final File rsrc : resources) {
-            getLog().debug("Adding resource " + rsrc);
-            if (rsrc.isDirectory()) {
-                DirectoryScanner ds = new DirectoryScanner();
-                ds.setBasedir(rsrc);
-                ds.setIncludes("**/*.*");
-                ds.scan();
+        // add additional resources
+        if (resources != null) {
+            for (final File rsrc : resources) {
+                getLog().debug("Adding resource " + rsrc);
+                if (rsrc.isDirectory()) {
+                    DirectoryScanner ds = new DirectoryScanner();
+                    ds.setBasedir(rsrc);
+                    ds.setIncludes("**/*.*");
+                    ds.scan();
 
-                if ( jarArchiver != null ) {
-                    for (String includedFile : ds.getIncludedFiles()) {
-                        jarArchiver.addFile(new File(rsrc, includedFile), 
includedFile);
+                    if ( jarArchiver != null ) {
+                        for (String includedFile : ds.getIncludedFiles()) {
+                            jarArchiver.addFile(new File(rsrc, includedFile), 
includedFile);
+                        }
+                    }
+                    if (sources != null) {
+                        final DefaultFileSet fileSet = new 
DefaultFileSet(rsrc);
+                        fileSet.setIncludingEmptyDirectories(false);
+                        fileSet.setIncludes(new String[] { "**/*.*" });
+                        sources.add(new DirectorySource(fileSet));
+                    }
+                } else {
+                    if ( jarArchiver != null ) {
+                        jarArchiver.addFile(rsrc, rsrc.getName());
+                    }
+                    if (sources != null) {
+                        sources.add(new FileSource(rsrc.getParentFile(), 
rsrc));
                     }
-                }
-                if (sources != null) {
-                    final DefaultFileSet fileSet = new DefaultFileSet(rsrc);
-                    fileSet.setIncludingEmptyDirectories(false);
-                    fileSet.setIncludes(new String[] { "**/*.*" });
-                    sources.add(new DirectorySource(fileSet));
-                }
-            } else {
-                if ( jarArchiver != null ) {
-                    jarArchiver.addFile(rsrc, rsrc.getName());
-                }
-                if (sources != null) {
-                    sources.add(new FileSource(rsrc.getParentFile(), rsrc));
                 }
             }
         }
     }
-}
 
     private void runProcessor(final ApisJarContext ctx,
         final ApiRegion apiRegion,
@@ -1636,13 +1678,19 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
     /**
      * Generate the javadoc
      * @param ctx The generation context
-     * @param region The region
+     * @param regionName The region name
+     * @param links The links used for javadoc generation
      * @param javadocDir The output directory
-     * @return {@code true} if generation succeeded
+     * @param regionSupport The region support
+     * @return A collection of artifacts used for the generation or {@code 
null} if no packages found
      * @throws MojoExecutionException on error
      */
-    private Collection<ArtifactInfo> generateJavadoc(final ApisJarContext ctx, 
final String regionName, final JavadocLinks links, final File javadocDir)
-            throws MojoExecutionException {
+    private Collection<ArtifactInfo> generateJavadoc(final ApisJarContext ctx,
+            final String regionName,
+            final JavadocLinks links,
+            final File javadocDir,
+            final RegionSupport regionSupport)
+    throws MojoExecutionException {
         final Collection<ArtifactInfo> usedInfos = new ArrayList<>();
 
         final List<String> sourceDirectories = new ArrayList<>();
@@ -1665,6 +1713,41 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
             return null;
         }
 
+        // handle additional packages
+        for(final Artifact artifact : 
ApisUtil.getAdditionalJavadocArtifacts(ctx, regionName) ) {
+            final boolean infoExists = ctx.getArtifactInfo(artifact.getId()) 
!= null;
+            final ArtifactInfo info = infoExists ?  
ctx.getArtifactInfo(artifact.getId()) : ctx.addArtifactInfo(artifact);
+
+            final Set<Clause> exportedPackages = 
regionSupport.getAllPublicPackages(ctx, artifact, 
getArtifactFile(artifact.getId()));
+            final Iterator<Clause> iter = exportedPackages.iterator();
+            final Set<String> exportedPackageNames = new LinkedHashSet<>();
+            while ( iter.hasNext() ) {
+                final Clause c = iter.next();
+                if ( javadocPackages.contains(c.getName()) ) {
+                    iter.remove();
+                } else {
+                    javadocPackages.add(c.getName());
+                    exportedPackageNames.add(c.getName());
+                }
+            }
+
+            if ( !exportedPackages.isEmpty() ) {
+                info.setUsedExportedPackages(regionName, exportedPackages, 
false);
+                if ( !infoExists ) {
+                    info.setUsedExportedPackages(exportedPackageNames);
+                    info.setSourceDirectory(new 
File(ctx.getDeflatedSourcesDir(), info.getId().toMvnName()));
+                    final boolean skipSourceDeflate = 
info.getSourceDirectory().exists();
+                    if (skipSourceDeflate) {
+                        getLog().debug("Source for artifact " + 
info.getId().toMvnName() + " already deflated");
+                    } else {
+                        this.downloadSources(ctx, info, artifact);
+                    }
+                }
+
+                usedInfos.add(info);
+                
sourceDirectories.add(info.getSourceDirectory().getAbsolutePath());
+            }
+        }
         javadocDir.mkdirs();
 
         final JavadocExecutor javadocExecutor = new 
JavadocExecutor(javadocDir.getParentFile())
@@ -1737,57 +1820,6 @@ public class ApisJarMojo extends 
AbstractIncludingFeatureMojo {
         return usedInfos;
     }
 
-    /**
-     * Get all packages contained in the archive
-     * @param file The archive to check
-     * @param extension The extension to check for
-     * @return A tuple of packages containing files with the extension and 
packages with files not having the extension
-     * @throws MojoExecutionException
-     */
-    private Map.Entry<Set<String>, Set<String>> getPackages(final 
ApisJarContext ctx, final File file, final String extension) throws 
MojoExecutionException {
-        final Set<String> packages = new TreeSet<>();
-        final Set<String> otherPackages = new TreeSet<>();
-
-        final Set<String> excludes = new HashSet<>();
-        for(final String v : ctx.getConfig().getBundleResourceFolders()) {
-            excludes.add(v.concat("/"));
-        }
-
-        try (final JarInputStream jis = new JarInputStream(new 
FileInputStream(file))) {
-            JarEntry entry;
-            while ((entry = jis.getNextJarEntry()) != null) {
-                if ( !entry.isDirectory() ) {
-                    boolean exclude = false;
-                    for(final String v : excludes) {
-                        if ( entry.getName().startsWith(v)) {
-                            exclude = true;
-                            break;
-                        }
-                    }
-                    if ( !exclude ) {
-                        final int lastPos = entry.getName().lastIndexOf('/');
-                        if (lastPos != -1) {
-                            final String packageName = 
entry.getName().substring(0, lastPos).replace('/', '.');
-
-                            if (entry.getName().endsWith(extension)) {
-                                packages.add(packageName);
-                            } else {
-                                otherPackages.add(packageName);
-                            }
-                        }
-                    }
-                }
-                jis.closeEntry();
-            }
-        } catch (final IOException ioe) {
-            throw new MojoExecutionException("Unable to scan file " + file + " 
: " + ioe.getMessage());
-        }
-
-        otherPackages.removeAll(packages);
-
-        return Collections.singletonMap(packages, 
otherPackages).entrySet().iterator().next();
-    }
-
     private File createLicenseReport(final ApisJarContext ctx,
             final ApiRegion region,
             final Collection<ArtifactInfo> infos,
diff --git 
a/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisConfiguration.java
 
b/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisConfiguration.java
index f63a665..41c5cdb 100644
--- 
a/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisConfiguration.java
+++ 
b/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisConfiguration.java
@@ -17,8 +17,10 @@
 package org.apache.sling.feature.maven.mojos.apis;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -65,7 +67,10 @@ import 
org.apache.sling.feature.maven.mojos.selection.IncludeExcludeMatcher;
  *   },
  *   "manifest-entries" : {
  *     "key" : "value"
- *   }
+ *   },
+ *   "javadoc-extensions" : [
+ *     "[[REGION_NAME]:][COMMA_SEPARATED_LIST_OF_ARTIFACT_EXTENSIONS"
+ *   ]
  * }
  * </pre>
  */
@@ -103,7 +108,7 @@ public class ApisConfiguration {
 
     private static final String PROP_LICENSE_HEADER = "license-header";
 
-
+    private static final String PROP_ADDITIONAL_JAVADOC_EXTENSIONS = 
"javadoc-extensions";
 
     private String licenseReport;
 
@@ -136,7 +141,14 @@ public class ApisConfiguration {
     private final Map<String, String> manifestEntries = new HashMap<>();
 
     private final Set<String> enabledToggles = new HashSet<>();
-    
+
+    /**
+     * A map for additional extensions used for javadoc generation.
+     * The key is the region name, "*" is used to indicate that these
+     * extensions should be added to all regions.
+     */
+    private final Map<String, Set<String>> additionJavadocExtensionNames = new 
HashMap<>();
+
     public ApisConfiguration(final Feature feature) throws 
MojoExecutionException {
         // check for extension
         final Extension ext = 
feature.getExtensions().getByName(EXTENSION_NAME);
@@ -165,6 +177,10 @@ public class ApisConfiguration {
             add(this.regionMappings, json, PROP_REGION_MAPPINGS);
             add(this.classifierMappings, json, PROP_CLASSIFIER_MAPPINGS);
             add(this.manifestEntries, json, PROP_MANIFEST_ENTRIES);
+
+            final List<String> additionalExtensions = new ArrayList<>();
+            add(additionalExtensions, json, 
PROP_ADDITIONAL_JAVADOC_EXTENSIONS);
+            this.setAdditionalJavadocExtensions(additionalExtensions);
         }
     }
 
@@ -186,6 +202,7 @@ public class ApisConfiguration {
             log.info("- " + PROP_LICENSE_DEFAULTS + " : " + 
this.licenseDefaults);
             log.info("- " + PROP_LICENSE_HEADER + " : " + 
this.licenseReportHeader);
             log.info("- " + PROP_LICENSE_FOOTER + " : " + 
this.licenseReportFooter);
+            log.info("- " + PROP_ADDITIONAL_JAVADOC_EXTENSIONS + " : " + 
this.additionJavadocExtensionNames);
         }
     }
 
@@ -411,10 +428,40 @@ public class ApisConfiguration {
             for(final String name : value.split(",")) {
                 enabledToggles.add(name.trim());
             }
-        }        
+        }
     }
 
     public Set<String> getEnabledToggles() {
         return this.enabledToggles;
     }
+
+    /**
+     * Add the additional extensions for javadoc generation
+     * @param javadocAdditionalExtensions A list of strings
+     */
+    public void setAdditionalJavadocExtensions(final List<String> 
javadocAdditionalExtensions) {
+        if ( javadocAdditionalExtensions != null ) {
+            for(final String val : javadocAdditionalExtensions) {
+                final int sepPos = val.indexOf(":");
+                final String regionName = sepPos == -1 ? "*" : 
val.substring(0, sepPos);
+                for(final String name : val.substring(sepPos+1).split(",")) {
+                    if ( !name.trim().isEmpty() ) {
+                        
this.additionJavadocExtensionNames.computeIfAbsent(regionName, key -> new 
LinkedHashSet<>()).add(name.trim());
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Get the map for additional javadoc extensions for a region
+     * @param regionName the region
+     * @return The set of extension names, might be empty
+     */
+    public Set<String> getAdditionalJavadocExtensions(final String regionName) 
{
+        final Set<String> result = new LinkedHashSet<>();
+        result.addAll(this.additionJavadocExtensionNames.getOrDefault("*", 
Collections.emptySet()));
+        
result.addAll(this.additionJavadocExtensionNames.getOrDefault(regionName, 
Collections.emptySet()));
+        return result;
+    }
 }
diff --git 
a/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisJarContext.java 
b/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisJarContext.java
index ea15025..28dbbc9 100644
--- 
a/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisJarContext.java
+++ 
b/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisJarContext.java
@@ -297,6 +297,15 @@ public class ApisJarContext {
         return info;
     }
 
+    public ArtifactInfo getArtifactInfo(final ArtifactId artifactId) {
+        for(final ArtifactInfo i : this.infos) {
+            if ( i.getArtifact().getId().equals(artifactId)) {
+                return i;
+            }
+        }
+        return null;
+    }
+    
     public List<ArtifactInfo> getArtifactInfos() {
         return this.infos;
     }
diff --git 
a/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisUtil.java 
b/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisUtil.java
index 18b5b2a..329eb15 100644
--- a/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisUtil.java
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/apis/ApisUtil.java
@@ -16,6 +16,8 @@
  */
 package org.apache.sling.feature.maven.mojos.apis;
 
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.LineNumberReader;
@@ -33,6 +35,9 @@ import java.util.Map;
 import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
 
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
@@ -44,6 +49,8 @@ import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.repository.RepositorySystem;
 import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.maven.mojos.apis.ApisJarContext.ArtifactInfo;
 import org.apache.sling.feature.maven.mojos.apis.spi.Processor;
 import org.apache.sling.feature.maven.mojos.selection.IncludeExcludeMatcher;
@@ -392,4 +399,79 @@ public class ApisUtil {
         }
         return result;
     }
+
+    /**
+     * Get all packages contained in the archive
+     * @param ctx The generation context
+     * @param file The archive to check
+     * @param extension The extension to check for
+     * @return A tuple of packages containing files with the extension and 
packages with files not having the extension
+     * @throws MojoExecutionException If processing fails
+     */
+    public static Map.Entry<Set<String>, Set<String>> getPackages(final 
ApisJarContext ctx, final File file, final String extension)
+            throws MojoExecutionException {
+        final Set<String> packages = new TreeSet<>();
+        final Set<String> otherPackages = new TreeSet<>();
+
+        final Set<String> excludes = new HashSet<>();
+        for(final String v : ctx.getConfig().getBundleResourceFolders()) {
+            excludes.add(v.concat("/"));
+        }
+
+        try (final JarInputStream jis = new JarInputStream(new 
FileInputStream(file))) {
+            JarEntry entry;
+            while ((entry = jis.getNextJarEntry()) != null) {
+                if ( !entry.isDirectory() ) {
+                    boolean exclude = false;
+                    for(final String v : excludes) {
+                        if ( entry.getName().startsWith(v)) {
+                            exclude = true;
+                            break;
+                        }
+                    }
+                    if ( !exclude ) {
+                        final int lastPos = entry.getName().lastIndexOf('/');
+                        if (lastPos != -1) {
+                            final String packageName = 
entry.getName().substring(0, lastPos).replace('/', '.');
+
+                            if (entry.getName().endsWith(extension)) {
+                                packages.add(packageName);
+                            } else {
+                                otherPackages.add(packageName);
+                            }
+                        }
+                    }
+                }
+                jis.closeEntry();
+            }
+        } catch (final IOException ioe) {
+            throw new MojoExecutionException("Unable to scan file " + file + " 
: " + ioe.getMessage());
+        }
+
+        otherPackages.removeAll(packages);
+
+        return Collections.singletonMap(packages, 
otherPackages).entrySet().iterator().next();
+    }
+
+    /**
+     * Get all artifacts from the configured extensions
+     * @param context The context
+     * @param regionName The name of the region
+     * @return A list of artifacts, might be empty
+     * @throws MojoExecutionException If processing fails or configuration is 
invalid
+     */
+    public static List<Artifact> getAdditionalJavadocArtifacts(final 
ApisJarContext context, final String regionName) throws MojoExecutionException {
+        final List<Artifact> result = new ArrayList<>();
+        for(final String extensionName : 
context.getConfig().getAdditionalJavadocExtensions(regionName)) {
+            final Extension extension = 
context.getFeature().getExtensions().getByName(extensionName);
+            if ( extension != null ) {
+                if ( extension.getType() != ExtensionType.ARTIFACTS ) {
+                    throw new MojoExecutionException("Extension " + 
extensionName + " must be of type artifacts.");
+                }
+                result.addAll(extension.getArtifacts());
+            }
+        }
+
+        return result;
+    }
 }
diff --git 
a/src/main/java/org/apache/sling/feature/maven/mojos/apis/RegionSupport.java 
b/src/main/java/org/apache/sling/feature/maven/mojos/apis/RegionSupport.java
index f67c94a..9952eb1 100644
--- a/src/main/java/org/apache/sling/feature/maven/mojos/apis/RegionSupport.java
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/apis/RegionSupport.java
@@ -20,6 +20,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Set;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
@@ -37,7 +38,7 @@ import 
org.apache.sling.feature.extension.apiregions.api.ApiRegions;
 import org.osgi.framework.Constants;
 
 public class RegionSupport {
-    
+
     private final Log log;
 
     private final boolean incrementalApis;
@@ -148,7 +149,7 @@ public class RegionSupport {
      *
      * @return Set of packages exported by this bundle and used in any region
      */
-    public Set<String> computeAllUsedExportPackages(final ApiRegions 
apiRegions, 
+    public Set<String> computeAllUsedExportPackages(final ApiRegions 
apiRegions,
             final Set<String> enabledToggles,
             final Clause[] exportedPackages,
             final Artifact bundle) throws MojoExecutionException {
@@ -188,7 +189,7 @@ public class RegionSupport {
      *
      * @return List of packages exported by this bundle and used in the region
      */
-    public Set<Clause> computeUsedExportPackagesPerRegion(final ApiRegion 
apiRegion, 
+    public Set<Clause> computeUsedExportPackagesPerRegion(final ApiRegion 
apiRegion,
             final Clause[] exportedPackages,
             final Set<String> allPackages) throws MojoExecutionException {
 
@@ -232,4 +233,30 @@ public class RegionSupport {
         }
     }
 
+    /**
+     * Get all packages for an artifact. If the artifact is a bundle use the 
export header, otherwise scan contents
+     * @param ctx The generation context
+     * @param artifact The artifact
+     * @param artifactFile The file
+     * @return A set of clauses
+     * @throws MojoExecutionException If processing fails
+     */
+    public Set<Clause> getAllPublicPackages(final ApisJarContext ctx, final 
Artifact artifact, final File artifactFile)
+            throws MojoExecutionException {
+        final Set<Clause> packages = new LinkedHashSet<>();
+
+        final Manifest manifest = getManifest(artifact.getId(), artifactFile);
+        if (  
manifest.getMainAttributes().getValue(Constants.BUNDLE_MANIFESTVERSION) != null 
) {
+            for(final Clause c : getExportedPackages(manifest)) {
+                packages.add(c);
+            }
+        } else {
+            final Set<String> names = ApisUtil.getPackages(ctx, artifactFile, 
ArtifactType.APIS.getContentExtension()).getKey();
+            for(final String n : names) {
+                packages.add(new Clause(n, null, null));
+            }
+        }
+
+        return packages;
+    }
 }

Reply via email to