Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven Plugin Fork Process With Proper Classpath

I am creating a Maven plugin with a rather unique requirement for proper operation: it needs to spawn new processes of itself and then wait for those processes to complete a task.

While this is relatively trivial to do on the command line, Maven plugins do not get invoked in the same manner as traditional Java code and thus there is no classpath. I cannot figure out how to resolve the correct classpath inside the plugin such that I can spawn a new JVM (invoking the Main method of another class inside the plugin).

Using the current artifact's MavenProject I am able to get an Artifact reference to myself (the plugin) and get it's relative directory inside the local Maven repository:

Artifact self = null;
for (Artifact artifact : project.getPluginArtifacts()) {
  if ("my-group-id".equals(artifact.getGroupId()) && "my-artifact-id".equals(artifact.getArtifactId())) {
    self = artifact;
    break;
  }
}
if (self == null) {
  throw new MojoExecutionException("Could not find representation of this plugin in project.");
}
for (ArtifactRepository artifactRepository : project.getPluginArtifactRepositories()) {
  String path = artifactRepository.pathOf(self);
  if (path != null) {
    getLog().info("relative path to self: " + path);
    break;
  }
}

How do I get a reference to all of its dependencies (and transitive dependencies) such that I can construct a full classpath for a new invocation? I see that self has a dependency filter but I don't know where to apply it.

Is this the proper way to create a new process of "myself" inside a plugin? Is there a better way?

like image 935
Jake Wharton Avatar asked Dec 26 '12 09:12

Jake Wharton


2 Answers

I found a great article on the differences between dependency resolution on Maven 2 and Maven 3.

Given an Artifact it boils down to the following:

private Set<Artifact> getDependenciesForArtifact(Artifact artifact) {
  ArtifactResolutionRequest arr = new ArtifactResolutionRequest()
      .setArtifact(artifact)
      .setResolveTransitively(true)
      .setLocalRepository(local);
  return repositorySystem.resolve(arr).getArtifacts();
}

With the Set you can construct a by calling pathOf on an ArtifactRepository for each element and joining with File.pathSeparator.

like image 196
Jake Wharton Avatar answered Oct 16 '22 03:10

Jake Wharton


Hm. Not really an answer but some hints. Why do you need such a complex thing? Furthermore i would take a deep look into the maven-surefire-plugin which can fork a jvm for unit tests and can handle classpath. On the other hand you can take a look into the maven-invoker or in the maven-invoker-plugin which can fork maven completely. Ah..what i missed. Take a look into the maven-dependency-plugin which has a particular goal for creating the classpath where you can take a look into the sources how they construct the classpath.

like image 31
khmarbaise Avatar answered Oct 16 '22 03:10

khmarbaise