You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by rf...@apache.org on 2021/04/30 11:42:40 UTC

[maven-javadoc-plugin] branch master updated: [MJAVADOC-634] Error in test-aggregate-no-fork when using modules

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 56799b5  [MJAVADOC-634] Error in test-aggregate-no-fork when using modules
56799b5 is described below

commit 56799b50296e517f3cdaf40ee74b5153c961cf67
Author: rfscholte <rf...@apache.org>
AuthorDate: Fri Apr 30 13:42:18 2021 +0200

    [MJAVADOC-634] Error in test-aggregate-no-fork when using modules
---
 .../invoker.properties                             |  18 +++
 .../MJAVADOC-634-module-testreports/pom.xml        |  52 ++++++++
 .../src/main/java/foo/Bar.java                     |  33 +++++
 .../src/main/java/module-info.java                 |  23 ++++
 .../src/test/java/foo/BarTest.java                 |  33 +++++
 .../maven/plugins/javadoc/AbstractJavadocMojo.java | 144 +++++++++------------
 .../maven/plugins/javadoc/JavadocModule.java       |  60 +++++++++
 .../maven/plugins/javadoc/JavadocReport.java       |   5 +-
 .../plugins/javadoc/resolver/ResourceResolver.java |  81 ++++++------
 9 files changed, 323 insertions(+), 126 deletions(-)

diff --git a/src/it/projects/MJAVADOC-634-module-testreports/invoker.properties b/src/it/projects/MJAVADOC-634-module-testreports/invoker.properties
new file mode 100644
index 0000000..83ac9c9
--- /dev/null
+++ b/src/it/projects/MJAVADOC-634-module-testreports/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+invoker.java.version = 11+
+invoker.goals = verify javadoc:test-aggregate-no-fork 
diff --git a/src/it/projects/MJAVADOC-634-module-testreports/pom.xml b/src/it/projects/MJAVADOC-634-module-testreports/pom.xml
new file mode 100644
index 0000000..83f9fdc
--- /dev/null
+++ b/src/it/projects/MJAVADOC-634-module-testreports/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>foo</groupId>
+  <artifactId>bar</artifactId>
+  <version>0.1.0-SNAPSHOT</version>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.8.1</version>
+          <configuration>
+            <release>11</release>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-javadoc-plugin</artifactId>
+          <version>@project.version@</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/src/it/projects/MJAVADOC-634-module-testreports/src/main/java/foo/Bar.java b/src/it/projects/MJAVADOC-634-module-testreports/src/main/java/foo/Bar.java
new file mode 100644
index 0000000..5c73698
--- /dev/null
+++ b/src/it/projects/MJAVADOC-634-module-testreports/src/main/java/foo/Bar.java
@@ -0,0 +1,33 @@
+package foo;
+
+/*
+ * 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.
+ */
+
+/**
+ * Bar.
+ */
+public class Bar
+{
+
+    public void run()
+    {
+        System.out.println( "Bar" );
+    }
+
+}
diff --git a/src/it/projects/MJAVADOC-634-module-testreports/src/main/java/module-info.java b/src/it/projects/MJAVADOC-634-module-testreports/src/main/java/module-info.java
new file mode 100644
index 0000000..0c2a1d2
--- /dev/null
+++ b/src/it/projects/MJAVADOC-634-module-testreports/src/main/java/module-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/**
+ * Foo.
+ */
+module foo {
+}
diff --git a/src/it/projects/MJAVADOC-634-module-testreports/src/test/java/foo/BarTest.java b/src/it/projects/MJAVADOC-634-module-testreports/src/test/java/foo/BarTest.java
new file mode 100644
index 0000000..4785b0d
--- /dev/null
+++ b/src/it/projects/MJAVADOC-634-module-testreports/src/test/java/foo/BarTest.java
@@ -0,0 +1,33 @@
+package foo;
+
+/*
+ * 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.
+ */
+
+/**
+ * BarTest.
+ */
+public class BarTest
+{
+
+    public void run()
+    {
+        System.out.println( "BarTest" );
+    }
+
+}
diff --git a/src/main/java/org/apache/maven/plugins/javadoc/AbstractJavadocMojo.java b/src/main/java/org/apache/maven/plugins/javadoc/AbstractJavadocMojo.java
index 2625251..add99dd 100644
--- a/src/main/java/org/apache/maven/plugins/javadoc/AbstractJavadocMojo.java
+++ b/src/main/java/org/apache/maven/plugins/javadoc/AbstractJavadocMojo.java
@@ -134,6 +134,7 @@ import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.Set;
 import java.util.StringTokenizer;
+import java.util.stream.Collectors;
 
 import static org.apache.commons.lang3.SystemUtils.isJavaVersionAtLeast;
 import static org.apache.maven.plugins.javadoc.JavadocUtil.toRelative;
@@ -1843,10 +1844,14 @@ public abstract class AbstractJavadocMojo
         {
             return null;
         }
-        else if ( project.getArtifact() != null )
+        else if ( project.getArtifact() != null && project.getArtifact().getFile() != null )
         {
             return project.getArtifact().getFile();
         }
+        else if ( project.getExecutionProject() != null && project.getExecutionProject().getArtifact() != null ) 
+        {
+            return project.getExecutionProject().getArtifact().getFile();
+        }
         return null;
     }
 
@@ -2018,9 +2023,11 @@ public abstract class AbstractJavadocMojo
             throw new MavenReportException( "Failed to generate javadoc options file: " + e.getMessage(), e );
         }
 
-        Map<String, Collection<Path>> sourcePaths = getSourcePaths();
+        Collection<JavadocModule> sourcePaths = getSourcePaths();
 
-        Collection<Path> collectedSourcePaths = collect( sourcePaths.values() );
+        Collection<Path> collectedSourcePaths = sourcePaths.stream()
+                                                           .flatMap( e -> e.getSourcePaths().stream() )
+                                                           .collect( Collectors.toList() );
 
         Map<Path, Collection<String>> files = getFiles( collectedSourcePaths );
         if ( !canGenerateReport( files ) )
@@ -2043,7 +2050,7 @@ public abstract class AbstractJavadocMojo
         }
         setFJavadocVersion( new File( jExecutable ) );
 
-        List<String> packageNames;
+        Collection<String> packageNames;
         if ( javadocRuntimeVersion.isAtLeast( "9" ) )
         {
             packageNames = getPackageNamesRespectingJavaModules( sourcePaths );
@@ -2249,16 +2256,6 @@ public abstract class AbstractJavadocMojo
         }
     }
 
-    protected final <T> Collection<T> collect( Collection<Collection<T>> sourcePaths )
-    {
-        Collection<T> collectedSourcePaths = new LinkedHashSet<>();
-        for ( Collection<T> sp : sourcePaths )
-        {
-            collectedSourcePaths.addAll( sp );
-        }
-        return collectedSourcePaths;
-    }
-
     /**
      * Method to get the files on the specified source paths
      *
@@ -2301,10 +2298,10 @@ public abstract class AbstractJavadocMojo
      * @throws MavenReportException {@link MavenReportException} issue while generating report
      * @see JavadocUtil#pruneDirs(MavenProject, Collection)
      */
-    protected Map<String, Collection<Path>> getSourcePaths()
+    protected Collection<JavadocModule> getSourcePaths()
         throws MavenReportException
     {
-        Map<String, Collection<Path>> mappedSourcePaths = new LinkedHashMap<>();
+        Collection<JavadocModule> mappedSourcePaths = new ArrayList<>();
 
         if ( StringUtils.isEmpty( sourcepath ) )
         {
@@ -2336,17 +2333,13 @@ public abstract class AbstractJavadocMojo
                 }
                 if ( !sourcePaths.isEmpty() )
                 {
-                    mappedSourcePaths.put( ArtifactUtils.versionlessKey( project.getGroupId(),
-                                                                         project.getArtifactId() ),
-                                           sourcePaths );
+                    mappedSourcePaths.add( new JavadocModule( ArtifactUtils.versionlessKey( project.getGroupId(),
+                                                                                            project.getArtifactId() ),
+                                                              getArtifactFile( project ),
+                                                              sourcePaths ) );
                 }
             }
 
-            if ( includeDependencySources )
-            {
-                mappedSourcePaths.putAll( getDependencySourcePaths() );
-            }
-
             if ( isAggregator() )
             {
                 for ( MavenProject subProject : getAggregatedProjects() )
@@ -2384,13 +2377,20 @@ public abstract class AbstractJavadocMojo
                         
                         if ( !additionalSourcePaths.isEmpty() )
                         {
-                            mappedSourcePaths.put( ArtifactUtils.versionlessKey( subProject.getGroupId(),
-                                                                                 subProject.getArtifactId() ),
-                                                   additionalSourcePaths );
+                            mappedSourcePaths.add( new JavadocModule( 
+                                                          ArtifactUtils.versionlessKey( subProject.getGroupId(),
+                                                                                        subProject.getArtifactId() ),
+                                                          getArtifactFile( subProject ),
+                                                          additionalSourcePaths ) );
                         }
                     }
                 }
             }
+
+            if ( includeDependencySources )
+            {
+                mappedSourcePaths.addAll( getDependencySourcePaths() );
+            }
         }
         else
         {
@@ -2406,8 +2406,10 @@ public abstract class AbstractJavadocMojo
             
             if ( !sourcePaths.isEmpty() )
             {
-                mappedSourcePaths.put( ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() ),
-                                       sourcePaths );
+                mappedSourcePaths.add( new JavadocModule( ArtifactUtils.versionlessKey( project.getGroupId(),
+                                                                                        project.getArtifactId() ),
+                                                          getArtifactFile( project ),
+                                                          sourcePaths ) );
             }
         }
 
@@ -2471,7 +2473,7 @@ public abstract class AbstractJavadocMojo
      * @return List of source paths.
      * @throws MavenReportException {@link MavenReportException}
      */
-    protected final Map<String, Collection<Path>> getDependencySourcePaths()
+    protected final Collection<JavadocModule> getDependencySourcePaths()
         throws MavenReportException
     {
         try
@@ -4521,43 +4523,31 @@ public abstract class AbstractJavadocMojo
      * @see #getFiles
      * @see #getSourcePaths()
      */
-    private List<String> getPackageNamesRespectingJavaModules( Map<String, Collection<Path>> allSourcePaths )
+    private Collection<String> getPackageNamesRespectingJavaModules( Collection<JavadocModule> javadocModules )
             throws MavenReportException
     {
-        List<String> returnList = new ArrayList<>();
-
         if ( !StringUtils.isEmpty( sourcepath ) )
         {
-            return returnList;
+            return Collections.emptyList();
         }
 
-        for ( Collection<Path> artifactSourcePaths: allSourcePaths.values() )
+        Set<String> returnList = new LinkedHashSet<>();
+        for ( JavadocModule javadocModule  : javadocModules )
         {
+            Collection<Path> artifactSourcePaths = javadocModule.getSourcePaths();
             Set<String> exportedPackages = new HashSet<>();
             boolean exportAllPackages;
-            File mainDescriptor = findMainDescriptor( artifactSourcePaths );
-            if ( mainDescriptor != null && !isTest() )
+            ResolvePathResult resolvedPath = getResolvePathResult( javadocModule.getArtifactFile() );
+            if ( resolvedPath != null && resolvedPath.getModuleNameSource() == ModuleNameSource.MODULEDESCRIPTOR )
             {
-                ResolvePathsRequest<File> request =
-                        ResolvePathsRequest.ofFiles( Collections.<File>emptyList() ).
-                                setMainModuleDescriptor( mainDescriptor );
-
-                try
+                Set<JavaModuleDescriptor.JavaExports> exports = resolvedPath.getModuleDescriptor().exports();
+                if ( exports.isEmpty() )
                 {
-                    Set<JavaModuleDescriptor.JavaExports> exports = locationManager.resolvePaths( request ).
-                            getMainModuleDescriptor().exports();
-                    if ( exports.isEmpty() )
-                    {
-                        continue;
-                    }
-                    for ( JavaModuleDescriptor.JavaExports export : exports )
-                    {
-                        exportedPackages.add( export.source() );
-                    }
+                    continue;
                 }
-                catch ( IOException e )
+                for ( JavaModuleDescriptor.JavaExports export : exports )
                 {
-                    throw new MavenReportException( e.getMessage(), e );
+                    exportedPackages.add( export.source() );
                 }
                 exportAllPackages = false;
             }
@@ -4801,7 +4791,7 @@ public abstract class AbstractJavadocMojo
      *      Reference Guide, Command line argument files</a>
      * @see #PACKAGES_FILE_NAME
      */
-    private void addCommandLinePackages( Commandline cmd, File javadocOutputDirectory, List<String> packageNames )
+    private void addCommandLinePackages( Commandline cmd, File javadocOutputDirectory, Collection<String> packageNames )
         throws MavenReportException
     {
         File packagesFile = new File( javadocOutputDirectory, PACKAGES_FILE_NAME );
@@ -4967,11 +4957,13 @@ public abstract class AbstractJavadocMojo
      */
     private void addJavadocOptions( File javadocOutputDirectory,
                                     List<String> arguments,
-                                    Map<String, Collection<Path>> allSourcePaths,
+                                    Collection<JavadocModule> allSourcePaths,
                                     Set<OfflineLink> offlineLinks )
         throws MavenReportException
     {
-        Collection<Path> sourcePaths = collect( allSourcePaths.values() );
+        Collection<Path> sourcePaths = allSourcePaths.stream()
+                                                     .flatMap( e -> e.getSourcePaths().stream() )
+                                                     .collect( Collectors.toList() );
 
         validateJavadocOptions();
 
@@ -5015,30 +5007,21 @@ public abstract class AbstractJavadocMojo
 
         if ( supportModulePath )
         {
-            for ( Map.Entry<String, Collection<Path>> entry : allSourcePaths.entrySet() )
+            for ( JavadocModule entry : allSourcePaths )
             {
-                MavenProject entryProject = reactorKeys.get( entry.getKey() );
-
-                File artifactFile;
-                if ( entryProject != null )
-                {
-                    artifactFile = getArtifactFile( entryProject );
-                }
-                else
-                {
-                    artifactFile = project.getArtifactMap().get( entry.getKey() ).getFile();
-                }
+                File artifactFile = entry.getArtifactFile();
+                
                 ResolvePathResult resolvePathResult = getResolvePathResult( artifactFile );
 
                 if ( resolvePathResult == null || resolvePathResult.getModuleNameSource() == ModuleNameSource.FILENAME )
                 {
-                    File moduleDescriptor = findMainDescriptor( entry.getValue() );
+                    Path moduleDescriptor = findMainDescriptor( entry.getSourcePaths() );
 
                     if ( moduleDescriptor != null )
                     {
                         try
                         {
-                            allModuleDescriptors.put( entry.getKey(),
+                            allModuleDescriptors.put( entry.getGa(),
                                       locationManager.parseModuleDescriptor( moduleDescriptor ).getModuleDescriptor() );
                         }
                         catch ( IOException e )
@@ -5049,7 +5032,7 @@ public abstract class AbstractJavadocMojo
                 }
                 else
                 {
-                    allModuleDescriptors.put( entry.getKey(), resolvePathResult.getModuleDescriptor() );
+                    allModuleDescriptors.put( entry.getGa(), resolvePathResult.getModuleDescriptor() );
                 }
             }
         }
@@ -5064,9 +5047,9 @@ public abstract class AbstractJavadocMojo
         if ( supportModulePath && !allModuleDescriptors.isEmpty() )
         {
             Collection<String> unnamedProjects = new ArrayList<>();
-            for ( Map.Entry<String, Collection<Path>> projectSourcepaths : allSourcePaths.entrySet() )
+            for ( JavadocModule javadocModule : allSourcePaths )
             {
-                MavenProject aggregatedProject = reactorKeys.get( projectSourcepaths.getKey() );
+                MavenProject aggregatedProject = reactorKeys.get( javadocModule.getGa() );
                 if ( aggregatedProject != null && !"pom".equals( aggregatedProject.getPackaging() ) )
                 {
                     ResolvePathResult result = null;
@@ -5095,7 +5078,7 @@ public abstract class AbstractJavadocMojo
                     }
                     else
                     {
-                        File moduleDescriptor = findMainDescriptor( projectSourcepaths.getValue() );
+                        Path moduleDescriptor = findMainDescriptor( javadocModule.getSourcePaths() );
 
                         if ( moduleDescriptor != null )
                         {
@@ -5119,7 +5102,7 @@ public abstract class AbstractJavadocMojo
 
                             additionalModules.add( result.getModuleDescriptor().name() );
 
-                            patchModules.put( result.getModuleDescriptor().name(), projectSourcepaths.getValue() );
+                            patchModules.put( result.getModuleDescriptor().name(), javadocModule.getSourcePaths() );
 
                             Path modulePath = moduleSourceDir.resolve( result.getModuleDescriptor().name() );
                             if ( !Files.isDirectory( modulePath ) )
@@ -5134,7 +5117,7 @@ public abstract class AbstractJavadocMojo
                     }
                     else
                     {
-                        unnamedProjects.add( projectSourcepaths.getKey() );
+                        unnamedProjects.add( javadocModule.getGa() );
                     }
 
                     if ( aggregatedProject.equals( getProject() ) )
@@ -5145,7 +5128,7 @@ public abstract class AbstractJavadocMojo
                 else
                 {
                     // todo
-                    getLog().error( "no reactor project: " + projectSourcepaths.getKey() );
+                    getLog().error( "no reactor project: " + javadocModule.getGa() );
                 }
             }
 
@@ -5192,7 +5175,6 @@ public abstract class AbstractJavadocMojo
         }
 
         if ( supportModulePath
-             && !isTest()
              && ( isAggregator()
                   || ModuleNameSource.MODULEDESCRIPTOR.equals( mainModuleNameSource )
                   || ModuleNameSource.MANIFEST.equals( mainModuleNameSource ) ) )
@@ -5403,13 +5385,13 @@ public abstract class AbstractJavadocMojo
         return resolvePathResult;
     }
 
-    private File findMainDescriptor( Collection<Path> roots ) throws MavenReportException
+    private Path findMainDescriptor( Collection<Path> roots ) throws MavenReportException
     {
         for ( Map.Entry<Path, Collection<String>> entry : getFiles( roots ).entrySet() )
         {
             if ( entry.getValue().contains( "module-info.java" ) )
             {
-                return entry.getKey().resolve( "module-info.java" ).toFile();
+                return entry.getKey().resolve( "module-info.java" );
             }
         }
         return null;
diff --git a/src/main/java/org/apache/maven/plugins/javadoc/JavadocModule.java b/src/main/java/org/apache/maven/plugins/javadoc/JavadocModule.java
new file mode 100644
index 0000000..31c6cc6
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/javadoc/JavadocModule.java
@@ -0,0 +1,60 @@
+package org.apache.maven.plugins.javadoc;
+
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Collection;
+
+/**
+ * Represents a unit of Javadoc referring to the binary and java source paths  
+ * 
+ * @since 3.3.0
+ */
+public class JavadocModule
+{
+    private final String ga;
+    
+    private final File artifactFile;
+    
+    private final Collection<Path> sourcePaths;
+
+    public JavadocModule( String ga, File artifactFile, Collection<Path> sourcePaths )
+    {
+        this.ga = ga;
+        this.artifactFile = artifactFile;
+        this.sourcePaths = sourcePaths;
+    }
+
+    public String getGa()
+    {
+        return ga;
+    }
+
+    public Collection<Path> getSourcePaths()
+    {
+        return sourcePaths;
+    }
+    
+    public File getArtifactFile()
+    {
+        return artifactFile;
+    }
+}
diff --git a/src/main/java/org/apache/maven/plugins/javadoc/JavadocReport.java b/src/main/java/org/apache/maven/plugins/javadoc/JavadocReport.java
index feeec56..7b10170 100644
--- a/src/main/java/org/apache/maven/plugins/javadoc/JavadocReport.java
+++ b/src/main/java/org/apache/maven/plugins/javadoc/JavadocReport.java
@@ -25,6 +25,7 @@ import java.util.Collection;
 import java.util.Locale;
 import java.util.Map;
 import java.util.ResourceBundle;
+import java.util.stream.Collectors;
 
 import org.apache.maven.doxia.siterenderer.RenderingContext;
 import org.apache.maven.doxia.siterenderer.sink.SiteRendererSink;
@@ -232,7 +233,9 @@ public class JavadocReport
             Map<Path, Collection<String>> files;
             try
             {
-                sourcePaths = collect( getSourcePaths().values() );
+                sourcePaths = getSourcePaths().stream()
+                                .flatMap( e -> e.getSourcePaths().stream() )
+                                .collect( Collectors.toList() );
                 files = getFiles( sourcePaths );
             }
             catch ( MavenReportException e )
diff --git a/src/main/java/org/apache/maven/plugins/javadoc/resolver/ResourceResolver.java b/src/main/java/org/apache/maven/plugins/javadoc/resolver/ResourceResolver.java
index d128648..01c7abc 100644
--- a/src/main/java/org/apache/maven/plugins/javadoc/resolver/ResourceResolver.java
+++ b/src/main/java/org/apache/maven/plugins/javadoc/resolver/ResourceResolver.java
@@ -19,22 +19,17 @@ package org.apache.maven.plugins.javadoc.resolver;
  * under the License.
  */
 
-
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.nio.file.Path;
-import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 
 import org.apache.maven.artifact.Artifact;
@@ -45,6 +40,7 @@ import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.plugins.javadoc.AbstractJavadocMojo;
+import org.apache.maven.plugins.javadoc.JavadocModule;
 import org.apache.maven.plugins.javadoc.JavadocUtil;
 import org.apache.maven.plugins.javadoc.ResourcesBundleMojo;
 import org.apache.maven.plugins.javadoc.options.JavadocOptions;
@@ -148,10 +144,10 @@ public final class ResourceResolver extends AbstractLogEnabled
      * @throws ArtifactResolutionException {@link ArtifactResolutionException}
      * @throws ArtifactNotFoundException {@link ArtifactNotFoundException}
      */
-    public Map<String, Collection<Path>> resolveDependencySourcePaths( final SourceResolverConfig config )
+    public Collection<JavadocModule> resolveDependencySourcePaths( final SourceResolverConfig config )
         throws ArtifactResolutionException, ArtifactNotFoundException
     {
-        final Map<String, Collection<Path>> mappedDirs = new LinkedHashMap<>();
+        final Collection<JavadocModule> mappedDirs = new ArrayList<>();
         
         final Map<String, MavenProject> projectMap = new HashMap<>();
         if ( config.reactorProjects() != null )
@@ -164,25 +160,26 @@ public final class ResourceResolver extends AbstractLogEnabled
 
         final List<Artifact> artifacts = config.project().getTestArtifacts();
 
-        final List<Artifact> forResourceResolution = new ArrayList<>( artifacts.size() );
         for ( final Artifact artifact : artifacts )
         {
             final String key = key( artifact.getGroupId(), artifact.getArtifactId() );
             final MavenProject p = projectMap.get( key );
             if ( p != null )
             {
-                mappedDirs.put( key, resolveFromProject( config, p, artifact ) );
+                mappedDirs.add( new JavadocModule( key, 
+                                                   artifact.getFile(),
+                                                   resolveFromProject( config, p, artifact ) ) );
             }
             else
             {
-                forResourceResolution.add( artifact );
+                JavadocModule m = resolveFromArtifact( config, artifact );
+                if ( m != null )
+                {
+                    mappedDirs.add( m );
+                }
             }
         }
 
-        for ( Map.Entry<String, Path> entry : resolveFromArtifacts( config, forResourceResolution ) )
-        {
-            mappedDirs.put( entry.getKey(), Collections.singletonList( entry.getValue() ) );
-        }
 
         return mappedDirs;
     }
@@ -261,14 +258,10 @@ public final class ResourceResolver extends AbstractLogEnabled
             }
         }
 
-        List<String> dirs = new ArrayList<>( toResolve.size() );
+        Collection<Path> dirs = new ArrayList<>( toResolve.size() );
         try
         {
-            for ( Map.Entry<String, Path> entry : resolveAndUnpack( toResolve, config, RESOURCE_VALID_CLASSIFIERS,
-                                                                      false ) )
-            {
-                dirs.add( entry.getValue().toString() );
-            }
+            dirs = resolveAndUnpack( toResolve, config, RESOURCE_VALID_CLASSIFIERS, false );
         }
         catch ( ArtifactResolutionException | ArtifactNotFoundException e )
         {
@@ -280,9 +273,9 @@ public final class ResourceResolver extends AbstractLogEnabled
 
         List<JavadocBundle> result = new ArrayList<>();
 
-        for ( String d : dirs )
+        for ( Path d : dirs )
         {
-            File dir = new File( d );
+            File dir = d.toFile();
             File resources = new File( dir, ResourcesBundleMojo.RESOURCES_DIR_PATH );
             JavadocOptions options = null;
 
@@ -306,32 +299,33 @@ public final class ResourceResolver extends AbstractLogEnabled
         return result;
     }
 
-    private Collection<Entry<String, Path>> resolveFromArtifacts( final SourceResolverConfig config,
-                                                      final List<Artifact> artifacts )
+    private JavadocModule resolveFromArtifact( final SourceResolverConfig config,
+                                                      final Artifact artifact )
         throws ArtifactResolutionException, ArtifactNotFoundException
     {
-        final List<Artifact> toResolve = new ArrayList<>( artifacts.size() );
+        final List<Artifact> toResolve = new ArrayList<>( 2 );
 
-        for ( final Artifact artifact : artifacts )
+        if ( config.filter() != null
+            && !new ArtifactIncludeFilterTransformer().transform( config.filter() ).include( artifact ) )
         {
-            if ( config.filter() != null
-                && !new ArtifactIncludeFilterTransformer().transform( config.filter() ).include( artifact ) )
-            {
-                continue;
-            }
+            return null;
+        }
 
-            if ( config.includeCompileSources() )
-            {
-                toResolve.add( createResourceArtifact( artifact, SOURCES_CLASSIFIER, config ) );
-            }
+        if ( config.includeCompileSources() )
+        {
+            toResolve.add( createResourceArtifact( artifact, SOURCES_CLASSIFIER, config ) );
+        }
 
-            if ( config.includeTestSources() )
-            {
-                toResolve.add( createResourceArtifact( artifact, TEST_SOURCES_CLASSIFIER, config ) );
-            }
+        if ( config.includeTestSources() )
+        {
+            toResolve.add( createResourceArtifact( artifact, TEST_SOURCES_CLASSIFIER, config ) );
         }
+        
+        Collection<Path> sourcePaths = resolveAndUnpack( toResolve, config, SOURCE_VALID_CLASSIFIERS, true ); 
 
-        return resolveAndUnpack( toResolve, config, SOURCE_VALID_CLASSIFIERS, true );
+        return new JavadocModule( key( artifact.getGroupId(), artifact.getArtifactId() ),
+                                  artifact.getFile(),
+                                  sourcePaths );
     }
 
     private Artifact createResourceArtifact( final Artifact artifact, final String classifier,
@@ -358,7 +352,7 @@ public final class ResourceResolver extends AbstractLogEnabled
      * @throws ArtifactResolutionException if an exception occurs
      * @throws ArtifactNotFoundException if an exception occurs
      */
-    private Collection<Map.Entry<String, Path>> resolveAndUnpack( final List<Artifact> artifacts,
+    private Collection<Path> resolveAndUnpack( final List<Artifact> artifacts,
                                                                     final SourceResolverConfig config,
                                                                     final List<String> validClassifiers,
                                                                     final boolean propagateErrors )
@@ -379,7 +373,7 @@ public final class ResourceResolver extends AbstractLogEnabled
             filter = null;
         }
         
-        final List<Map.Entry<String, Path>> result = new ArrayList<>( artifacts.size() );
+        final List<Path> result = new ArrayList<>( artifacts.size() );
         for ( final Artifact a : artifactSet )
         {
             if ( !validClassifiers.contains( a.getClassifier() ) || ( filter != null && !filter.include( a ) ) )
@@ -414,8 +408,7 @@ public final class ResourceResolver extends AbstractLogEnabled
 
                 unArchiver.extract();
 
-                result.add( new AbstractMap.SimpleEntry<>( key( a.getGroupId(), a.getArtifactId() ),
-                                                           d.toPath().toAbsolutePath() ) );
+                result.add( d.toPath().toAbsolutePath() );
             }
             catch ( final NoSuchArchiverException e )
             {