On 08/02/2012 04:58 AM, Anders Hammar wrote:
not have a dependency on some library in the plugin itself but rely on it being
declared as a dependency in the Maven project where the plugin is bound. That
made it
totally controllable by the project.
If the build-time code would not normally already be a dependency of the project - your main concern - then you could have the mojo configuration accept a parameter typed
as a list of "dependencies". (org.apache.maven.model.Dependency[]?) These would then have to be resolved (transitively) against pluginRepositories, and used to construct
a URL[] to pass to a URLClassLoader (possibly prepended to the project's regular dependencies). Thus the project could declare e.g.
<dependencies>
<dependency>
<groupId>some.framework</>
<artifactId>the-api</>
</>
<dependency>
<groupId>some.framework</>
<artifactId>the-impl</>
<scope>runtime</>
</>
</>
<build>
<plugins>
<plugin>
<groupId>some.framework</>
<artifactId>the-plugin</>
<configuration>
<toolDependencies>
<dependency>
<groupId>some.framework</>
<artifactId>the-build-tool</>
</>
</>
</>
</>
</>
</>
Naturally you still need to be careful that a given version of the-plugin - specifically, that part of its code which will link against classes loaded by the
URLClassLoader - is API-compatible with past, present, and foreseeable future versions of the-build-tool. If there are known breaking API changes, a single version of the
plugin could also supply multiple adapters tuned to different version ranges of the-build-tool, or use reflection to try several method variants, or at least catch
LinkageError and report the problem gracefully.
A mojo like this could be awkward to write from scratch; would be best to have an archetype for it. In particular, if you are using direct Java linkage between the-plugin
code and the-build-tool (rather than, say, reflection), and the-plugin does not have a direct dependency on any version of the-build-tool (i.e. <toolDependencies> is
mandatory and not just an optional selection of an alternative version) and/or supports multiple incompatible version ranges of the-build-tool, then to build the-plugin
itself you need a multimodule project:
the-plugin-parent
the-build-tool-abstraction (jar)
the-build-tool-adapter-v1 (jar) -> the-build-tool-abstraction, the-build-tool
@ [1.0.0,2)
the-build-tool-adapter-v2 (jar) -> the-build-tool-abstraction, the-build-tool
@ [2.0.0,3)
the-plugin (maven-plugin) -> the-build-tool-abstraction
Here the-plugin resolves <toolDependencies> and determines which major version of the-build-tool is being requested ("1" or "2"). It then constructs a URLClassLoader
parented to the plugin ClassLoader (or whatever loads classes from the-build-tool-abstraction) including everything from <toolDependencies> (resolved from
pluginRepositories) plus the appropriate the-build-tool-adapter-v* (also from pluginRepositories), creates an instance of an interface defined in
the-build-tool-abstraction and implemented in the-build-tool-adapter-v* (selected via java.util.ServiceLoader, Plexus @Component, ClassLoader.loadClass("hardcoded"),
etc.), and casts to the-build-tool-abstraction interface which the plugin can directly "see". Then it calls methods on this instance to run the build tool.
Even if you are sure the-build-tool will be API-compatible it is not wise to mash everything into one project. While the-plugin could declare a <scope>provided</>
dependency on the-build-tool, as the developer of the-plugin you would need to be careful to keep track of which src/main/java/**/*.java are permitted to refer to types
in the-build-tool and which are not; furthermore, the URLClassLoader would then need to override loadClass to _not_ delegate loading of these classes to its parent (since
then they would be loaded by the plugin class loader and fail to resolve against the-build-tool). Using a multimodule project as sketched above documents and enforces the
runtime structure and means that the URLClassLoader can use normal parent delegation.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]