io.repaint.maven.tiles.TilesMavenLifecycleParticipant.groovy Maven / Gradle / Ivy
/*
* **********************************************************************************************************************
*
* Maven Tiles
*
***********************************************************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
**********************************************************************************************************************/
package io.repaint.maven.tiles
import groovy.transform.CompileStatic
import groovy.transform.TypeCheckingMode
import org.apache.maven.AbstractMavenLifecycleParticipant
import org.apache.maven.MavenExecutionException
import org.apache.maven.RepositoryUtils
import org.apache.maven.artifact.Artifact
import org.apache.maven.artifact.DefaultArtifact
import org.apache.maven.artifact.handler.DefaultArtifactHandler
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout
import org.apache.maven.artifact.resolver.ArtifactNotFoundException
import org.apache.maven.artifact.resolver.ArtifactResolutionException
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest
import org.apache.maven.artifact.resolver.ArtifactResolver
import org.apache.maven.artifact.resolver.ResolutionErrorHandler
import org.apache.maven.artifact.versioning.VersionRange
import org.apache.maven.execution.MavenSession
import org.apache.maven.model.Build
import org.apache.maven.model.Dependency
import org.apache.maven.model.DistributionManagement
import org.apache.maven.model.Model
import org.apache.maven.model.Parent
import org.apache.maven.model.Plugin
import org.apache.maven.model.PluginManagement
import org.apache.maven.model.Repository
import org.apache.maven.model.building.DefaultModelBuilder
import org.apache.maven.model.building.DefaultModelBuildingRequest
import org.apache.maven.model.building.FileModelSource
import org.apache.maven.model.building.ModelBuilder
import org.apache.maven.model.building.ModelBuildingListener
import org.apache.maven.model.building.ModelBuildingRequest
import org.apache.maven.model.building.ModelBuildingResult
import org.apache.maven.model.building.ModelProcessor
import org.apache.maven.model.building.ModelSource
import org.apache.maven.model.building.ModelSource2
import org.apache.maven.model.io.ModelParseException
import org.apache.maven.model.resolution.InvalidRepositoryException
import org.apache.maven.model.resolution.ModelResolver
import org.apache.maven.model.resolution.UnresolvableModelException
import org.apache.maven.plugin.MojoExecution
import org.apache.maven.plugin.PluginParameterExpressionEvaluator
import org.apache.maven.plugin.descriptor.MojoDescriptor
import org.apache.maven.project.DefaultModelBuildingListener
import org.apache.maven.project.MavenProject
import org.apache.maven.project.ProjectBuilder
import org.apache.maven.project.ProjectBuildingHelper
import org.apache.maven.shared.filtering.MavenFileFilter
import org.apache.maven.shared.filtering.MavenResourcesFiltering
import org.codehaus.plexus.component.annotations.Component
import org.codehaus.plexus.component.annotations.Requirement
import org.codehaus.plexus.logging.Logger
import org.codehaus.plexus.util.xml.pull.XmlPullParserException
import org.eclipse.aether.impl.VersionRangeResolver
import org.eclipse.aether.resolution.VersionRangeRequest
import org.xml.sax.SAXParseException
import static io.repaint.maven.tiles.Constants.TILEPLUGIN_ARTIFACT
import static io.repaint.maven.tiles.Constants.TILEPLUGIN_GROUP
import static io.repaint.maven.tiles.Constants.TILE_POM
import static io.repaint.maven.tiles.GavUtil.artifactGav
import static io.repaint.maven.tiles.GavUtil.artifactName
import static io.repaint.maven.tiles.GavUtil.modelGav
import static io.repaint.maven.tiles.GavUtil.modelRealGa
import static io.repaint.maven.tiles.GavUtil.parentGav
/**
* Fetches all dependencies defined in the POM `configuration`.
*
* Merging operation is delegated to {@link DefaultModelBuilder}
*
* @author: Richard Vowles - https://plus.google.com/+RichardVowles
* @author: Mark Derricutt - https://plus.google.com/+MarkDerricutt
*
*/
@CompileStatic
@Component(role = AbstractMavenLifecycleParticipant, hint = "TilesMavenLifecycleParticipant")
public class TilesMavenLifecycleParticipant extends AbstractMavenLifecycleParticipant {
public static final String TILEPLUGIN_KEY = "${TILEPLUGIN_GROUP}:${TILEPLUGIN_ARTIFACT}"
@Requirement
Logger logger
@Requirement
ArtifactResolver resolver
@Requirement
ResolutionErrorHandler resolutionErrorHandler
@Requirement
ProjectBuilder projectBuilder
@Requirement
ModelBuilder modelBuilder
@Requirement
ModelProcessor modelProcessor
@Requirement
ProjectBuildingHelper projectBuildingHelper
@Requirement
ArtifactRepositoryFactory repositoryFactory
@Requirement( role = ArtifactRepositoryLayout.class )
Map repositoryLayouts
@Requirement
VersionRangeResolver versionRangeResolver
@Requirement
MavenFileFilter mavenFileFilter
@Requirement
MavenResourcesFiltering mavenResourcesFiltering
NotDefaultModelCache modelCache
MavenSession mavenSession
class ArtifactModel {
public Artifact artifact
public TileModel tileModel
public ArtifactModel(Artifact artifact, TileModel tileModel) {
this.artifact = artifact
this.tileModel = tileModel
}
}
/**
* We store the groupId:artifactId -> Artifact of those tiles we have discovered in our meanderings through
* the
*/
Map processedTiles = [:]
List tileDiscoveryOrder = []
Map unprocessedTiles = [:]
String applyBeforeParent;
/**
* This specifically goes and asks the repository for the "tile" attachment for this pom, not the
* pom itself (because we don't care about that).
*/
protected static Artifact getArtifactFromCoordinates(String groupId, String artifactId, String type, String classifier, String version) {
return new DefaultArtifact(groupId, artifactId, VersionRange.createFromVersion(version), "compile",
type, classifier, new DefaultArtifactHandler(type))
}
/**
* Return the given Artifact's .pom artifact
*/
protected static Artifact getPomArtifactForArtifact(Artifact artifact) {
return getArtifactFromCoordinates(artifact.groupId, artifact.artifactId, 'pom', '', artifact.version)
}
protected Artifact resolveTile(MavenSession mavenSession, MavenProject project, Artifact tileArtifact) throws MavenExecutionException {
// try to find tile from reactor
if (mavenSession != null) {
List allProjects = mavenSession.getProjects()
if (allProjects != null) {
for (MavenProject currentProject : allProjects) {
if (currentProject.groupId == tileArtifact.groupId && currentProject.artifactId == tileArtifact.artifactId && currentProject.version == tileArtifact.version) {
tileArtifact.file = FilteringHelper.getTile(currentProject, mavenSession, mavenFileFilter, mavenResourcesFiltering)
return tileArtifact
}
}
}
}
try {
resolveVersionRange(project, tileArtifact)
// Resolve the .xml file for the tile
final def tileReq = new ArtifactResolutionRequest()
.setArtifact(tileArtifact)
.setRemoteRepositories(project?.remoteArtifactRepositories)
.setLocalRepository(mavenSession?.localRepository)
resolutionErrorHandler.throwErrors(tileReq, resolver.resolve(tileReq))
// Resolve the .pom file for the tile
Artifact pomArtifact = getPomArtifactForArtifact(tileArtifact)
final def pomReq = new ArtifactResolutionRequest()
.setArtifact(pomArtifact)
.setRemoteRepositories(project?.remoteArtifactRepositories)
.setLocalRepository(mavenSession?.localRepository)
resolutionErrorHandler.throwErrors(pomReq, resolver.resolve(pomReq))
// When resolving from workspace (e.g. m2e, intellij) we might receive the path to pom.xml instead of the attached tile
if (tileArtifact.file && tileArtifact.file.name == "pom.xml") {
File tileFile = new File(tileArtifact.file.parent, TILE_POM)
if (!tileFile.exists()) {
throw new MavenExecutionException("Tile ${artifactGav(tileArtifact)} cannot be resolved.",
tileFile as File)
}
MavenProject tileProject = projectBuilder.build(pomArtifact.file, mavenSession.request.projectBuildingRequest).getProject()
tileArtifact.file = FilteringHelper.getTile(tileProject, mavenSession, mavenFileFilter, mavenResourcesFiltering)
}
if (System.getProperty("performRelease")?.asBoolean()) {
if (tileArtifact.version.endsWith("-SNAPSHOT")) {
throw new MavenExecutionException("Tile ${artifactGav(tileArtifact)} is a SNAPSHOT and we are releasing.",
tileArtifact.getFile() as File)
}
}
} catch (ArtifactResolutionException e) {
throw new MavenExecutionException(e.getMessage(), e)
} catch (ArtifactNotFoundException e) {
throw new MavenExecutionException(e.getMessage(), e)
}
return tileArtifact
}
protected static Artifact turnPropertyIntoUnprocessedTile(String artifactGav, File pomFile)
throws MavenExecutionException {
String[] gav = artifactGav.tokenize(":")
if (gav.size() != 3 && gav.size() != 5) {
throw new MavenExecutionException("${artifactGav} does not have the form group:artifact:version-range or group:artifact:extension:classifier:version-range", pomFile as File)
}
String groupId = gav[0]
String artifactId = gav[1]
String version
String type = "xml"
String classifier = ""
if (gav.size() == 3) {
version = gav[2]
} else {
type = gav[2]
classifier = gav[3]
version = gav[4]
}
return getArtifactFromCoordinates(groupId, artifactId, type, classifier, version)
}
protected TileModel loadModel(Artifact artifact) throws MavenExecutionException {
try {
TileModel modelLoader = new TileModel(artifact.getFile(), artifact)
logger.debug(String.format("Loaded Maven Tile %s", artifactGav(artifact)))
return modelLoader
} catch (FileNotFoundException e) {
throw new MavenExecutionException(String.format("Error loading %s", artifactGav(artifact)), e)
} catch (XmlPullParserException e) {
throw new MavenExecutionException(String.format("Error building %s", artifactGav(artifact)), e)
} catch (SAXParseException sax) {
throw new MavenExecutionException(String.format("Error building %s", artifactGav(artifact)), sax)
} catch (IOException e) {
throw new MavenExecutionException(String.format("Error parsing %s", artifactGav(artifact)), e)
}
}
/**
* Invoked after all MavenProject instances have been created.
*
* This callback is intended to allow extensions to manipulate MavenProjects
* before they are sorted and actual build execution starts.
*/
public void afterProjectsRead(MavenSession mavenSession)
throws MavenExecutionException {
this.mavenSession = mavenSession
this.modelCache = new NotDefaultModelCache(mavenSession)
// disabled explicit lookup as these seem to be injected just fine. Are these required for eclipse m2e>
//repositoryFactory = mavenSession.container.lookup(ArtifactRepositoryFactory)
//repositoryLayouts = mavenSession.lookupMap(ArtifactRepositoryLayout.class.getName()) as Map
List allProjects = mavenSession.getProjects()
if (allProjects != null) {
for (MavenProject currentProject : allProjects) {
boolean containsTiles = currentProject.getPluginArtifactMap().keySet().contains(TILEPLUGIN_KEY)
if (containsTiles) {
Plugin plugin = currentProject.getPlugin(TILEPLUGIN_KEY);
List subModules = currentProject.getModules()
if (plugin.isInherited() && subModules != null && subModules.size() > 0) {
Model currentModel = currentProject.getModel();
for (MavenProject otherProject : allProjects) {
Parent otherParent = otherProject.getModel().getParent()
if (otherParent != null && parentGav(otherParent) == modelGav(currentModel)) {
// We're in project with children, fail the build immediately. This is both an opinionated choice, but also
// one of project health - with tile definitions in parent POMs usage of -pl, -am, and -amd maven options
// are limited.
throw new MavenExecutionException("Usage of maven-tiles prohibited from multi-module builds where reactor is used as parent.", currentProject.getFile())
}
}
}
orchestrateMerge(mavenSession, currentProject)
// did we expect but not get a distribution artifact repository?
if (!currentProject.distributionManagementArtifactRepository) {
discoverAndSetDistributionManagementArtifactoryRepositoriesIfTheyExist(currentProject)
}
}
}
}
}
/**
* If we get here, we have a Tiles project that might have a distribution management section but it is playing
* dicky-birds and hasn't set up the distribution management repositories.
*
* @param project
*/
void discoverAndSetDistributionManagementArtifactoryRepositoriesIfTheyExist(MavenProject project) {
DistributionManagement distributionManagement = project.model.distributionManagement
if (distributionManagement) {
if (distributionManagement.repository) {
project.setReleaseArtifactRepository(repositoryFactory.createDeploymentArtifactRepository(
distributionManagement.repository.id, distributionManagement.repository.url,
repositoryLayouts.get( distributionManagement.repository.layout ?: 'default' ), true ))
}
if (distributionManagement.snapshotRepository) {
project.setSnapshotArtifactRepository(repositoryFactory.createDeploymentArtifactRepository(
distributionManagement.snapshotRepository.id, distributionManagement.snapshotRepository.url,
repositoryLayouts.get( distributionManagement.snapshotRepository.layout ?: 'default' ), true ))
}
}
}
/**
* Merges the files over the top of the project, and then the individual project back over the top.
* The reason for this is that the super pom and packaging can set plugin versions. This allows the tiles
* to overwrite those, and then if they are manually specified in the pom, they then get set again.
* @param project - the currently evaluated project
* @throws MavenExecutionException
*/
protected void orchestrateMerge(MavenSession mavenSession, MavenProject project) throws MavenExecutionException {
// Clear collected tiles from previous project in reactor
processedTiles.clear();
tileDiscoveryOrder.clear();
unprocessedTiles.clear();
// collect the first set of tiles
parseConfiguration(project.model, project.file)
// collect any unprocessed tiles, and process them causing them to potentially load more unprocessed ones
loadAllDiscoveredTiles(mavenSession, project)
// don't do anything if there are no tiles
if (processedTiles) {
thunkModelBuilder(project)
}
}
@CompileStatic(TypeCheckingMode.SKIP)
protected void thunkModelBuilder(MavenProject project) {
List tiles = processedTiles.values().collect({it.tileModel})
if (!tiles) return
ModelBuildingListener modelBuildingListener = new DefaultModelBuildingListener(project,
projectBuildingHelper, mavenSession.request.projectBuildingRequest)
// new org.apache.maven.project.PublicDefaultModelBuildingListener( project,
//projectBuildingHelper, mavenSession.request.projectBuildingRequest )
// this allows us to know when the ModelProcessor is called that we should inject the tiles into the
// parent structure
ModelSource2 mainArtifactModelSource = createModelSource(project.file)
ModelBuildingRequest request = new DefaultModelBuildingRequest(modelSource: mainArtifactModelSource,
pomFile: project.file, modelResolver: createModelResolver(project), modelCache: modelCache,
systemProperties: mavenSession.request.systemProperties, userProperties: mavenSession.request.userProperties,
profiles: mavenSession.request.projectBuildingRequest.profiles,
activeProfileIds: mavenSession.request.projectBuildingRequest.activeProfileIds,
inactiveProfileIds: mavenSession.request.projectBuildingRequest.inactiveProfileIds,
modelBuildingListener: modelBuildingListener,
locationTracking: true, twoPhaseBuilding: true, processPlugins: true)
boolean tilesInjected = false
ModelProcessor delegateModelProcessor = new ModelProcessor() {
@Override
File locatePom(File projectDirectory) {
return modelProcessor.locatePom(projectDirectory)
}
@Override
Model read(File input, Map options) throws IOException, ModelParseException {
return modelProcessor.read(input, options)
}
@Override
Model read(Reader input, Map options) throws IOException, ModelParseException {
return modelProcessor.read(input, options)
}
@Override
Model read(InputStream input, Map options) throws IOException, ModelParseException {
Model model = modelProcessor.read(input, options)
use(GavUtil) {
// evaluate the model version to deal with CI friendly build versions.
// "0-SNAPSHOT" indicates an undefined property.
if (model.artifactId == project.artifactId && model.realGroupId == project.groupId
&& (evaluateString(model.realVersion) == project.version || evaluateString(model.realVersion) == "0-SNAPSHOT")
&& model.packaging == project.packaging) {
// we're at the first (project) level. Apply tiles here if no explicit parent is set
if (!applyBeforeParent) {
injectTilesIntoParentStructure(tiles, model, request)
tilesInjected = true
}
} else if (modelRealGa(model) == applyBeforeParent) {
// we're at the level with the explicitly selected parent. Apply the tiles here
injectTilesIntoParentStructure(tiles, model, request)
tilesInjected = true
} else if (model.packaging == 'tile' || model.packaging == 'pom') {
// we could be at a parent that is a tile. In this case return the precomputed model
TileModel oneOfUs = tiles.find { TileModel tm ->
Model tileModel = tm.model
return (model.artifactId == tileModel.artifactId && model.realGroupId == tileModel.realGroupId &&
model.realVersion == tileModel.realVersion)
}
if (oneOfUs) {
model = oneOfUs.model
}
}
// if we want to apply tiles at a specific parent and have not come by it yet, we need
// to make the parent reference project specific, so that it will not pick up a cached
// version. We do this by adding a project specific suffix, which will later be removed
// when actually loading that parent.
if (applyBeforeParent && !tilesInjected && model.parent) {
// remove the parent from the cache which causes it to be reloaded through our ModelProcessor
request.modelCache.put(model.parent.groupId, model.parent.artifactId, model.parent.version,
org.apache.maven.model.building.ModelCacheTag.RAW.getName(), null)
}
}
return model
}
}
((DefaultModelBuilder)modelBuilder).setModelProcessor(delegateModelProcessor)
try {
ModelBuildingResult interimBuild = modelBuilder.build(request)
// this will revert the tile dependencies inserted by TilesProjectBuilder, which is fine since by now they
// served their purpose of correctly ordering projects, so we can now do without them
ModelBuildingResult finalModel = modelBuilder.build(request, interimBuild)
if (!tilesInjected && applyBeforeParent) {
throw new MavenExecutionException("Cannot apply tiles, the expected parent ${applyBeforeParent} is not found.",
project.file)
}
copyModel(project, finalModel.effectiveModel)
} finally {
// restore original ModelProcessor
((DefaultModelBuilder)modelBuilder).setModelProcessor(modelProcessor)
}
}
ModelSource2 createModelSource(File pomFile) {
return new ModelSource2() {
InputStream stream = pomFile.newInputStream()
@Override
InputStream getInputStream() throws IOException {
return stream
}
@Override
String getLocation() {
return pomFile.absolutePath
}
@Override
URI getLocationURI() {
return pomFile.toURI()
}
@Override
ModelSource2 getRelatedSource(String relPath) {
File relatedPom = new File(pomFile.parentFile, relPath)
if (relatedPom.isDirectory()) {
relatedPom = new File(relatedPom, "pom.xml")
}
if (relatedPom.isFile()&& relatedPom.canRead()) {
return createModelSource(relatedPom.canonicalFile)
}
return null
}
}
}
protected ModelResolver createModelResolver(MavenProject project) {
// this is for resolving parents, so always poms
return new ModelResolver() {
@Override
ModelSource2 resolveModel(String groupId, String artifactId, String version) throws UnresolvableModelException {
Artifact artifact = new DefaultArtifact(groupId, artifactId, VersionRange.createFromVersion(version), "compile",
"pom", null, new DefaultArtifactHandler("pom"))
resolveVersionRange(project, artifact)
final def req = new ArtifactResolutionRequest()
.setArtifact(artifact)
.setRemoteRepositories(project?.remoteArtifactRepositories)
.setLocalRepository(mavenSession?.localRepository)
resolutionErrorHandler.throwErrors(req, resolver.resolve(req))
return createModelSource(artifact.file)
}
@Override
ModelSource2 resolveModel(Parent parent) throws UnresolvableModelException {
return resolveModel(parent.groupId, parent.artifactId, parent.version)
}
// this exists in later versions of maven
ModelSource resolveModel(Dependency dependency) throws UnresolvableModelException {
return resolveModel(dependency.groupId, dependency.artifactId, dependency.version)
}
@Override
void addRepository(Repository repository) throws InvalidRepositoryException {
}
@Override
void addRepository(Repository repository, boolean wat) throws InvalidRepositoryException {
}
@Override
ModelResolver newCopy() {
return createModelResolver(project)
}
}
}
/**
* This is out of static type checking because the method is private and the class ModelCacheTag
* is package-private.
*
* @param model - the model we are inserting into the cache
* @param request - the building request, it holds the cache reference
* @param pomFile - the pomFile is required for model data for Maven 3.2.x not for 3.0.x
*/
@CompileStatic(TypeCheckingMode.SKIP)
protected void putModelInCache(Model model, ModelBuildingRequest request, File pomFile) {
// stuff it in the cache so it is ready when requested rather than it trying to be resolved.
request.modelCache.put(model.groupId, model.artifactId, evaluateString(model.version),
org.apache.maven.model.building.ModelCacheTag.RAW.getName(),
org.apache.maven.model.building.ModelCacheTag.RAW.intoCache(
new org.apache.maven.model.building.ModelData(new FileModelSource(pomFile), model, model.groupId, model.artifactId, model.version)))
}
/**
* Creates a chain of tile parents based on how we discovered them and inserts them into the parent
* chain, above this project and before this project's parent (if any)
*
* @param tiles - tiles that should make up part of the collection
* @param pomModel - the current project
* @param request - the request to build the current project
*/
void injectTilesIntoParentStructure(List tiles, Model pomModel, ModelBuildingRequest request) {
Parent originalParent = pomModel.parent
Model lastPom = pomModel
File lastPomFile = request.pomFile
// fix up the version of the originalParent
if (originalParent != null) {
originalParent.version = evaluateString(originalParent.version)
}
if (tiles) {
// evaluate the model version to deal with CI friendly build versions
logger.info("--- tiles-maven-plugin: Injecting ${tiles.size()} tiles as intermediary parent artifacts for ${evaluateString(modelRealGa(pomModel))}...")
logger.info("Mixed '${evaluateString(modelGav(pomModel))}' with tile '${evaluateString(modelGav(tiles.first().model))}' as its new parent.")
// if there is a parent make sure the inherited groupId / version is correct
if (!pomModel.groupId) {
pomModel.groupId = originalParent.groupId
logger.info("Explicitly set groupId to '${pomModel.groupId}' from original parent '${parentGav(originalParent)}'.")
}
if (!pomModel.version) {
pomModel.version = originalParent.version
logger.info("Explicitly set version to '${pomModel.version}' from original parent '${parentGav(originalParent)}'.")
}
}
tiles.each { TileModel tileModel ->
Model model = tileModel.model
Parent modelParent = new Parent(groupId: model.groupId, version: evaluateString(model.version), artifactId: model.artifactId)
lastPom.parent = modelParent
if (pomModel != lastPom) {
putModelInCache(lastPom, request, lastPomFile)
logger.info("Mixed '${evaluateString(modelGav(lastPom))}' with tile '${evaluateString(parentGav(modelParent))}' as its new parent.")
}
lastPom = model
lastPomFile = tileModel.tilePom
}
lastPom.parent = originalParent
logger.info("Mixed '${evaluateString(modelGav(lastPom))}' with original parent '${parentGav(originalParent)}' as its new top level parent.")
logger.info("")
if (pomModel != lastPom) {
putModelInCache(lastPom, request, lastPomFile)
}
}
protected static void copyModel(MavenProject project, Model newModel) {
// no setting parent, we have generated an effective model which is now all copied in
Model projectModel = project.model
projectModel.build = newModel.build
projectModel.dependencyManagement = newModel.dependencyManagement
projectModel.dependencies = newModel.dependencies
projectModel.repositories = newModel.repositories
projectModel.pluginRepositories = newModel.pluginRepositories
projectModel.licenses = newModel.licenses
projectModel.scm = newModel.scm
projectModel.distributionManagement = newModel.distributionManagement
projectModel.developers = newModel.developers
projectModel.contributors = newModel.contributors
projectModel.organization = newModel.organization
projectModel.mailingLists = newModel.mailingLists
projectModel.issueManagement = newModel.issueManagement
projectModel.ciManagement = newModel.ciManagement
projectModel.profiles = newModel.profiles
projectModel.prerequisites = newModel.prerequisites
projectModel.properties = newModel.properties
projectModel.reporting = newModel.reporting
// update model (test) source directory, which is the first entry and might have been set through a tile
if (projectModel.build.sourceDirectory) {
project.compileSourceRoots[0] = projectModel.build.sourceDirectory;
}
if (projectModel.build.testSourceDirectory) {
project.testCompileSourceRoots[0] = projectModel.build.testSourceDirectory;
}
// for tile provided LifecycleMapping in m2e we need to modifiy the original model
Plugin m2ePlugin = projectModel.build.pluginManagement?.getPluginsAsMap()?.get("org.eclipse.m2e:lifecycle-mapping")
if (m2ePlugin) {
Build build = project.originalModel.build
if (!build) {
build = new Build()
project.originalModel.build = build
}
if (build.pluginManagement) {
build.pluginManagement = build.pluginManagement.clone()
} else {
build.pluginManagement = new PluginManagement()
}
build.pluginManagement.addPlugin(m2ePlugin)
}
}
protected void loadAllDiscoveredTiles(MavenSession mavenSession, MavenProject project) throws MavenExecutionException {
while (unprocessedTiles.size() > 0) {
String unresolvedTile = unprocessedTiles.keySet().iterator().next()
Artifact resolvedTile = resolveTile(mavenSession, project, unprocessedTiles.remove(unresolvedTile))
TileModel tileModel = loadModel(resolvedTile)
// ensure we have resolved the tile (it could come from a non-tile model)
if (tileModel) {
processedTiles.put(artifactName(resolvedTile), new ArtifactModel(resolvedTile, tileModel))
parseForExtendedSyntax(tileModel, resolvedTile.getFile())
}
}
ensureAllTilesDiscoveredAreAccountedFor()
}
/**
* removes all invalid tiles from the discovery order
*/
void ensureAllTilesDiscoveredAreAccountedFor() {
List missingTiles = []
tileDiscoveryOrder.each { String tile ->
if (!processedTiles[tile]) {
missingTiles.add(tile)
}
}
tileDiscoveryOrder.removeAll(missingTiles)
}
/**
* Normally used inside the current project's pom file when declaring the tile plugin. People may prefer this
* to use to include tiles however in a tile.xml
*/
@CompileStatic(TypeCheckingMode.SKIP)
protected void parseConfiguration(Model model, File pomFile) {
def configuration = model.build?.plugins
?.find({ Plugin plugin -> plugin.groupId == TILEPLUGIN_GROUP && plugin.artifactId == TILEPLUGIN_ARTIFACT})
?.configuration
if (configuration) {
configuration.getChild("tiles")?.children?.each { tile ->
processConfigurationTile(model, tile.value, pomFile)
}
applyBeforeParent = configuration.getChild("applyBefore")?.value
}
}
/**
* Used for when we have a TileModel (we have read directly) so we support the extra syntax.
*/
protected void parseForExtendedSyntax(TileModel model, File pomFile) {
model.tiles.each { String tileGav ->
processConfigurationTile(model.model, tileGav, pomFile)
}
parseConfiguration(model.model, pomFile)
}
protected void processConfigurationTile(Model model, String tileDependencyName, File pomFile) {
Artifact unprocessedTile = turnPropertyIntoUnprocessedTile(tileDependencyName, pomFile)
String depName = artifactName(unprocessedTile)
if (!processedTiles.containsKey(depName)) {
if (unprocessedTiles.containsKey(depName)) {
logger.warn(String.format("tiles-maven-plugin in project %s requested for same tile dependency %s",
modelGav(model), artifactGav(unprocessedTile)))
} else {
logger.debug("Adding tile ${artifactGav(unprocessedTile)}")
unprocessedTiles.put(depName, unprocessedTile)
tileDiscoveryOrder.add(depName)
}
} else {
logger.warn(String.format("tiles-maven-plugin in project %s requested for same tile dependency %s",
modelGav(model), artifactGav(unprocessedTile)))
}
}
/**
* Evaluate a string for property substitution. This method is null tolerant and utilizes the mavenSession
* class member if set.
*
* @param value The String to evaluate
* @return The evaluated String
*/
protected String evaluateString(String value) {
if ((value != null) && (mavenSession != null)) {
return new PluginParameterExpressionEvaluator(mavenSession, new MojoExecution(new MojoDescriptor()))
.evaluate(value, String.class)
} else {
return value
}
}
void resolveVersionRange(MavenProject project, Artifact tileArtifact) {
def versionRangeRequest = new VersionRangeRequest(RepositoryUtils.toArtifact(tileArtifact),
RepositoryUtils.toRepos(project?.remoteArtifactRepositories),
null)
def versionRangeResult = versionRangeResolver.resolveVersionRange(mavenSession?.repositorySession, versionRangeRequest)
if (versionRangeResult?.versions) {
tileArtifact.version = versionRangeResult.highestVersion
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy