I'm trying to develop a Maven plugin that looks for certain classes and generates specific documentation for them. I've built a POC as a unit test. I'm trying to convert that now to a Maven plugin.
The test code has access to the classes of the project + the classes of any dependency. I'd like to have that "same classloader" (or a classloader with the same access) available in my Maven plugin.
Is this possible?
Creating a classloader that contains the classes of the project is doable:
@Mojo(name = "tao-generator", defaultPhase = LifecyclePhase.INSTALL)
public class TaoGeneratorMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", required = true, readonly = true)
MavenProject project;
...
@SneakyThrows
private ClassLoader getClassLoader(MavenProject project) {
List<URL> runtimeUrls = new ArrayList<>();
List<String> runtimeClasspathElements = project.getRuntimeClasspathElements();
for (int i = 0; i < runtimeClasspathElements.size(); i++) {
String element = runtimeClasspathElements.get(i);
runtimeUrls.add(new File(element).toURI().toURL());
}
URL[] array = new URL[runtimeUrls.size()];
array = runtimeUrls.toArray(array);
return new URLClassLoader(array,
Thread.currentThread().getContextClassLoader());
}
I haven't figured out how to create a classloader that has access to the dependencies classes. Can I use a similar technique, starting from MavenProject project
?
I've also tried to load the classes directly from the generated fat Spring Boot jar. That doesn't work with a simple URLClassLoader, since that classloader isn't able to load classes from nested jars. Maybe this could be the starting point of another angle to make this work?
You can access the dependencies by calling project.getArtifacts()
. From its javadoc:
All dependencies that this project has, including transitive ones. Contents are lazily populated, so depending on what phases have run dependencies in some scopes won't be included. eg. if only compile phase has run, dependencies with scope test won't be included.
You can use attributes on @Mojo
to control the dependencies that are available. Specifically, you need to set both requiresDependencyResolution
and requiresDependencyCollection
to ResolutionScope.TEST
.