11

I'd like to use Google Reflections to scan classes from the compiled project from my Maven plugin. But plugins by default don't see the compiled classes of the project. From Maven 3 documentation I read:

Plugins that need to load classes from the compile/runtime/test class path of a project need to create a custom URLClassLoader in combination with the mojo annotation @requiresDependencyResolution.

Which is a bit vague to say the least. Basically I would need a reference to a classloader that loads the compiled project classes. How do I get that?

EDIT:

Ok, the @Mojo annotation has requiresDependencyResolution parameter, so that's easy but still need the correct way to build a classloader.

vertti
  • 7,539
  • 4
  • 51
  • 81
  • I think "compile (...) class path of a project" really still refers to its dependencies, and you're down to: "a custom class loader needs to be created". – Sander Verhagen Nov 01 '13 at 07:22
  • I don't understand what the blocker is here. A Google for custom classloader will provide plenty of examples. If all else fails you can also take a peek at the source of an existing Maven plugin that works on project classes and borrow some bits and bobs. – Gimby Nov 01 '13 at 09:53

1 Answers1

12
@Component
private MavenProject project;

@SuppressWarnings("unchecked")
@Override
public void execute() throws MojoExecutionException {
    List<String> classpathElements = null;
    try {
        classpathElements = project.getCompileClasspathElements();
        List<URL> projectClasspathList = new ArrayList<URL>();
        for (String element : classpathElements) {
            try {
                projectClasspathList.add(new File(element).toURI().toURL());
            } catch (MalformedURLException e) {
                throw new MojoExecutionException(element + " is an invalid classpath element", e);
            }
        }

        URLClassLoader loader = new URLClassLoader(projectClasspathList.toArray(new URL[0]));
        // ... and now you can pass the above classloader to Reflections

    } catch (ClassNotFoundException e) {
        throw new MojoExecutionException(e.getMessage());
    } catch (DependencyResolutionRequiredException e) {
        new MojoExecutionException("Dependency resolution failed", e);
    }
}
CupawnTae
  • 14,192
  • 3
  • 29
  • 60
vertti
  • 7,539
  • 4
  • 51
  • 81
  • If You do URLClassLoader loader = new URLClassLoader(projectClasspathList.toArray(new URL[0]), Thread.currentThread().getContextClassLoader()); Then the classes You load as plugin dependencies will be instances of the same, that would be returned by Reflections – maslan May 25 '16 at 07:36
  • Thanks! I had ClassNotFoundExceptions from within my plugin logic, using Class names returned by `Reflections#getAllTypes()` until I `Class.forName(type, true, loader)` where loader is your loader – juanmf Aug 02 '16 at 11:07