I've reimplemented MavenImporter support, as known from ShrinkWrap Maven Resolver 1.1.X and made it available in 2.X stream (https://github.com/shrinkwrap/resolver/pull/29) . Let me describe how it would be useful and what are the implementation details.
MavenImporter should do following: pick up a maven project defined by pom.xml and return an Archive<?>
Previous implementation kind of did so, however it relied on mvn package being run first. This made it broken from IDE and often there were some other gliches.
While trying to construct a WAR file from a POM file, I realized what is the biggest problem. The problem lies in Java classes to be included. These classes could be lying anywhere on the filesystem and they are maybe even not compiled at the time you want to import. This means that MavenImporter must mimic Maven. This is something I haven't realized at first, but it is actually the only way how it could work.
So, how it works? You want to build a JavaArchive defined by a pom.xml:
JavaArchive war = ShrinkWrap.create(MavenImporter.class).loadPomFromFile("src/it/jar-sample/pom.xml") .importBuildOutput(/* you can pass a strategy here, however it won't do anything for jars */) .as(JavaArchive.class); WebArchive war = ShrinkWrap.create(MavenImporter.class).loadPomFromFile("src/it/war-sample/pom.xml") .importBuildOutput(/* you can pass a strategy here and package something else then default scopes*/) .as(WebArchive.class);
What happens internally?
- Pom file is processed and type of PackagingProcessor is inferred
- All dependencies needed for compilation as fetched via Shrinkres
- All java classes are compiled
- Original archive is merged with compiled results
- Resources are added
- Optional steps. These basically differ for archive type, e.g. in War we add webapp resources and Maven dependencies
- Archive is casted to desired type
What changes were done to Shrinkres?
- new module api-maven-archive - this contains MavenImporter
- new module spi-maven-archive - this contains PackagingProcessor
- impl-maven-archive module contains importer impl, processors plus abstract processor for compilation purposes
- MavenWorkingSession was made API and moved to api-maven
- ParsedPomFile abstraction of POM Model in api-maven
- MavenWorkingSessionImpl was simplied
- MavenWorkingSessionTask can now return arbitrary object
- Some of the functionality was wrapped into tasks so it can be shared more easily in between MavenImporter and Maven Resolver
- plexus-utils in impl-maven (not runtime anymore, needed for Xpp3Dom plugin configuration processing
- plexus-compiler-javac, plexus-component-api in impl-maven-archive - needed to compile sources with javac
What is not implemented yet and where the contributors are welcomed:
- support for configure settings.xml
- support for EAR archive (and any other archive type)
- resource includes/excludes
- (maven) resource filtering support
- manifest support
- dropping integration-tests component, it won't be needed anymore
What is the performance?
- dunno, but we compiled java files are cached, resolved archifacts are cached on filesystem in Maven local repository. Packaging an example WAR, which is a part of integration tests, takes 2 seconds on my system, which I find reasonably good.
As everything is modular and decoupled, we can improve implementation slowly so 99% of users project can be packaged via MavenImporter. IMHO this is the last API part we have to figure out until we can lock the API and become beta, so I'd like you guys to identify whether we could live with "new" API (MavenSession, ParsedPomFile) in a longer term.
How does this sound to you? Can it be merged into 2.0.0-alpha-6?