Skip to content

Commit c145867

Browse files
committed
Add findEffectiveReactor method
The build reactor determined by Maven is constructed based on execution. This means that multi-module projects will not be part of the same reactor if Maven is invoked from an individual submodule. The findEffectiveReactor method makes a best-effort to discover the complete intended reactor in a multi-module project by following all parent and module linkages.
1 parent 6139a8c commit c145867

File tree

1 file changed

+98
-2
lines changed

1 file changed

+98
-2
lines changed

src/main/java/org/scijava/maven/plugin/DependencyUtils.java

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
* %%
88
* Redistribution and use in source and binary forms, with or without
99
* modification, are permitted provided that the following conditions are met:
10-
*
10+
*
1111
* 1. Redistributions of source code must retain the above copyright notice,
1212
* this list of conditions and the following disclaimer.
1313
* 2. Redistributions in binary form must reproduce the above copyright notice,
1414
* this list of conditions and the following disclaimer in the documentation
1515
* and/or other materials provided with the distribution.
16-
*
16+
*
1717
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1818
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1919
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -30,15 +30,28 @@
3030

3131
package org.scijava.maven.plugin;
3232

33+
import java.io.File;
34+
import java.util.ArrayList;
35+
import java.util.HashSet;
36+
import java.util.List;
37+
import java.util.Properties;
38+
import java.util.Set;
39+
3340
import org.apache.maven.artifact.Artifact;
3441
import org.apache.maven.artifact.repository.ArtifactRepository;
3542
import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
3643
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
3744
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
45+
import org.apache.maven.execution.MavenSession;
46+
import org.apache.maven.profiles.DefaultProfileManager;
47+
import org.apache.maven.profiles.ProfileManager;
3848
import org.apache.maven.project.MavenProject;
49+
import org.apache.maven.project.MavenProjectBuilder;
50+
import org.apache.maven.project.ProjectBuildingException;
3951
import org.apache.maven.shared.dependency.tree.DependencyNode;
4052
import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
4153
import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
54+
import org.codehaus.plexus.PlexusContainer;
4255

4356
/**
4457
* Utility class for initiating Maven-based dependency checks.
@@ -126,8 +139,91 @@ public static void checkDependencies(final MavenProject mavenProject,
126139
}
127140
}
128141

142+
/**
143+
* Manually constructs an list of effective reactor projects by recursively
144+
* searching parent and submodule projects. This allows the intention of the
145+
* reactor to be preserved, as long as it is fully available on disk, even
146+
* when building a submodule directly.
147+
*
148+
* @param defaultReactor Return value to use if a comprehensive list can not
149+
* be discovered.
150+
* @param baseProject {@link MavenProject} where invocation started.
151+
* @return A list of MavenProjects that can be treated as though within the
152+
* current reactor.
153+
* @throws ProjectBuildingException
154+
*/
155+
public static List<MavenProject> findEffectiveReactor(
156+
final List<MavenProject> defaultReactor, final MavenSession session,
157+
final MavenProject baseProject, final MavenProjectBuilder projectBuilder,
158+
final ArtifactRepository localRepository) throws ProjectBuildingException
159+
{
160+
final Set<MavenProject> reactor = new HashSet<MavenProject>();
161+
final Set<MavenProject> visited = new HashSet<MavenProject>();
162+
final ProfileManager profileManager = getProfileManager(session);
163+
164+
findEffectiveReactor(reactor, visited, baseProject, baseProject,
165+
projectBuilder, localRepository, profileManager);
166+
167+
if (reactor.size() <= 1 || !reactor.contains(baseProject)) return defaultReactor;
168+
return new ArrayList<MavenProject>(reactor);
169+
}
170+
129171
// -- Helper methods --
130172

173+
/**
174+
* Helper method to recursively populate a set of {@link MavenProject}s that
175+
* can be considered to be within the same reactor.
176+
*/
177+
private static void findEffectiveReactor(final Set<MavenProject> reactor,
178+
final Set<MavenProject> visited, final MavenProject currentProject,
179+
final MavenProject target, final MavenProjectBuilder projectBuilder,
180+
final ArtifactRepository localRepository,
181+
final ProfileManager profileManager) throws ProjectBuildingException
182+
{
183+
// short-circuit if already visited this project
184+
if (!visited.add(currentProject)) return;
185+
186+
final File baseDir = currentProject.getBasedir();
187+
188+
// We only are interested in local projects
189+
if (baseDir != null && baseDir.exists()) {
190+
191+
// If the current project lists any modules , then that project itself
192+
// needs to be included in the reactor
193+
if (currentProject.getModules().size() > 0) {
194+
reactor.add(currentProject);
195+
}
196+
197+
// Recursively add each submodule to the reactor
198+
for (final Object o : currentProject.getModules()) {
199+
final File submodule =
200+
new File(baseDir.getAbsolutePath() + File.separator + o.toString() +
201+
File.separator + "pom.xml");
202+
final MavenProject p =
203+
projectBuilder.build(submodule, localRepository, profileManager);
204+
reactor.add(p);
205+
findEffectiveReactor(reactor, visited, p, target, projectBuilder,
206+
localRepository, profileManager);
207+
}
208+
}
209+
210+
// Recurse into parent
211+
if (currentProject.hasParent()) findEffectiveReactor(reactor, visited,
212+
currentProject.getParent(), target, projectBuilder, localRepository,
213+
profileManager);
214+
}
215+
216+
/**
217+
* Convenience method to get the {@link ProfileManager} for a given
218+
* {@link MavenSession}.
219+
*/
220+
@SuppressWarnings("deprecation")
221+
private static ProfileManager getProfileManager(final MavenSession session) {
222+
final PlexusContainer container = session.getContainer();
223+
final Properties execution = session.getExecutionProperties();
224+
return new DefaultProfileManager(container, execution);
225+
}
226+
131227
/**
132228
* Helper method to build an {@link ArtifactFilter}. Multiple filters can be
133229
* unioned together via the {@link AndArtifactFilter}.

0 commit comments

Comments
 (0)