mirror of
https://github.com/bmlong137/maven-tiles
synced 2025-10-01 14:41:08 +00:00
Merge pull request #101 from rbygrave/master
ENH: Support explicit merging of tiles execution configuration
This commit is contained in:
@@ -40,6 +40,7 @@ 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.PluginExecution
|
||||
import org.apache.maven.model.PluginManagement
|
||||
import org.apache.maven.model.Repository
|
||||
import org.apache.maven.model.building.DefaultModelBuilder
|
||||
@@ -68,6 +69,7 @@ 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.Xpp3Dom
|
||||
import org.codehaus.plexus.util.xml.pull.XmlPullParserException
|
||||
import org.eclipse.aether.impl.VersionRangeResolver
|
||||
import org.eclipse.aether.resolution.VersionRangeRequest
|
||||
@@ -108,7 +110,7 @@ public class TilesMavenLifecycleParticipant extends AbstractMavenLifecyclePartic
|
||||
|
||||
@Requirement
|
||||
ProjectBuilder projectBuilder
|
||||
|
||||
|
||||
@Requirement
|
||||
ModelBuilder modelBuilder
|
||||
|
||||
@@ -154,6 +156,8 @@ public class TilesMavenLifecycleParticipant extends AbstractMavenLifecyclePartic
|
||||
Map<String, ArtifactModel> processedTiles = [:]
|
||||
List<String> tileDiscoveryOrder = []
|
||||
Map<String, Artifact> unprocessedTiles = [:]
|
||||
Map<String,TileModel> tilesByExecution = [:];
|
||||
|
||||
String applyBeforeParent;
|
||||
|
||||
/**
|
||||
@@ -359,9 +363,10 @@ public class TilesMavenLifecycleParticipant extends AbstractMavenLifecyclePartic
|
||||
*/
|
||||
protected void orchestrateMerge(MavenSession mavenSession, MavenProject project) throws MavenExecutionException {
|
||||
// Clear collected tiles from previous project in reactor
|
||||
processedTiles.clear();
|
||||
tileDiscoveryOrder.clear();
|
||||
unprocessedTiles.clear();
|
||||
processedTiles.clear()
|
||||
tileDiscoveryOrder.clear()
|
||||
unprocessedTiles.clear()
|
||||
tilesByExecution.clear()
|
||||
|
||||
// collect the first set of tiles
|
||||
parseConfiguration(project.model, project.file)
|
||||
@@ -467,7 +472,7 @@ public class TilesMavenLifecycleParticipant extends AbstractMavenLifecyclePartic
|
||||
try {
|
||||
ModelBuildingResult interimBuild = modelBuilder.build(request)
|
||||
|
||||
// this will revert the tile dependencies inserted by TilesProjectBuilder, which is fine since by now they
|
||||
// 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) {
|
||||
@@ -687,6 +692,8 @@ public class TilesMavenLifecycleParticipant extends AbstractMavenLifecyclePartic
|
||||
}
|
||||
|
||||
protected void loadAllDiscoveredTiles(MavenSession mavenSession, MavenProject project) throws MavenExecutionException {
|
||||
|
||||
List<TileModel> mergeSourceTiles = []
|
||||
while (unprocessedTiles.size() > 0) {
|
||||
String unresolvedTile = unprocessedTiles.keySet().iterator().next()
|
||||
|
||||
@@ -696,14 +703,102 @@ public class TilesMavenLifecycleParticipant extends AbstractMavenLifecyclePartic
|
||||
|
||||
// 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())
|
||||
if (hasProperty(tileModel, 'tile-merge-source')) {
|
||||
// hold and merge into target later
|
||||
mergeSourceTiles.add(tileModel)
|
||||
} else {
|
||||
if (hasProperty(tileModel, 'tile-merge-target')) {
|
||||
registerTargetTile(tileModel)
|
||||
}
|
||||
String tileName = artifactName(resolvedTile)
|
||||
processedTiles.put(tileName, new ArtifactModel(resolvedTile, tileModel))
|
||||
parseForExtendedSyntax(tileModel, resolvedTile.getFile())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// merge all the source tiles last
|
||||
for (TileModel mergeTile : mergeSourceTiles) {
|
||||
mergeTileIntoTarget(mergeTile)
|
||||
}
|
||||
|
||||
ensureAllTilesDiscoveredAreAccountedFor()
|
||||
}
|
||||
|
||||
private static boolean hasProperty(TileModel tileModel, String propertyKey) {
|
||||
// remove these properties, we don't want them in the merged result
|
||||
return 'true' == tileModel.model?.properties?.remove(propertyKey)
|
||||
}
|
||||
|
||||
private List<Plugin> registerTargetTile(TileModel targetTile) {
|
||||
return mergeTile(targetTile, false)
|
||||
}
|
||||
|
||||
private List<Plugin> mergeTileIntoTarget(TileModel fragmentTile) {
|
||||
return mergeTile(fragmentTile, true)
|
||||
}
|
||||
|
||||
private List<Plugin> mergeTile(TileModel tileModel, boolean mergeIntoTarget) {
|
||||
|
||||
tileModel.model?.build?.plugins?.each { plugin ->
|
||||
plugin.executions.each { execution ->
|
||||
String eid = "$plugin.groupId:$plugin.artifactId:$execution.id"
|
||||
if (!mergeIntoTarget) {
|
||||
tilesByExecution.put(eid, tileModel)
|
||||
} else {
|
||||
String fragmentId = "$tileModel.model.groupId:$tileModel.model.artifactId"
|
||||
TileModel targetTile = tilesByExecution.get(eid)
|
||||
if (targetTile) {
|
||||
String targetId = "$targetTile.model.groupId:$targetTile.model.artifactId"
|
||||
logger.info("Merged tile $fragmentId into $targetId plugin:$eid")
|
||||
mergeProperties(targetTile, tileModel)
|
||||
mergeExecutionConfiguration(targetTile, execution, eid)
|
||||
} else {
|
||||
String missingTileId = tileModel.model?.properties?.getProperty('tile-merge-expected-target')
|
||||
if (missingTileId) {
|
||||
throw new MavenExecutionException("Please add missing tile $missingTileId. This is required for tile $fragmentId, plugin:$eid", (Throwable)null)
|
||||
} else {
|
||||
throw new MavenExecutionException("Error with tile $fragmentId - Missing target tile required with plugin:$eid. Please check the documentation for this tile.", (Throwable)null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the properties from the mergeTile into targetTile.
|
||||
*/
|
||||
private static void mergeProperties(TileModel targetTile, TileModel mergeTile) {
|
||||
if (mergeTile.model.properties) {
|
||||
targetTile.model.properties.putAll(mergeTile.model.properties)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the execution configuration from mergeExecution into the target tile.
|
||||
*/
|
||||
private void mergeExecutionConfiguration(TileModel targetTile, PluginExecution mergeExecution, String eid) {
|
||||
|
||||
targetTile.model?.build?.plugins?.each { plugin ->
|
||||
plugin.executions.each { execution ->
|
||||
String targetEid = "$plugin.groupId:$plugin.artifactId:$execution.id"
|
||||
if (targetEid.equals(eid)) {
|
||||
Xpp3Dom configuration = (Xpp3Dom)execution.configuration
|
||||
String appendElementName = configuration.getAttribute('tiles-append')
|
||||
if (appendElementName) {
|
||||
Xpp3Dom target = configuration.getChild(appendElementName)
|
||||
Xpp3Dom source = ((Xpp3Dom)mergeExecution.configuration).getChild(appendElementName)
|
||||
// append from source into target
|
||||
Xpp3Dom.mergeXpp3Dom(target, source, false)
|
||||
|
||||
logger.debug("merged execution configuration - $eid")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* removes all invalid tiles from the discovery order
|
||||
*/
|
||||
@@ -787,8 +882,7 @@ public class TilesMavenLifecycleParticipant extends AbstractMavenLifecyclePartic
|
||||
|
||||
void resolveVersionRange(MavenProject project, Artifact tileArtifact) {
|
||||
def versionRangeRequest = new VersionRangeRequest(RepositoryUtils.toArtifact(tileArtifact),
|
||||
RepositoryUtils.toRepos(project?.remoteArtifactRepositories),
|
||||
null)
|
||||
RepositoryUtils.toRepos(project?.remoteArtifactRepositories), null)
|
||||
|
||||
def versionRangeResult = versionRangeResolver.resolveVersionRange(mavenSession?.repositorySession, versionRangeRequest)
|
||||
|
||||
|
@@ -30,6 +30,7 @@ import org.apache.maven.model.Build
|
||||
import org.apache.maven.model.Model
|
||||
import org.apache.maven.model.Parent
|
||||
import org.apache.maven.model.Plugin
|
||||
import org.apache.maven.model.PluginExecution
|
||||
import org.apache.maven.model.building.ModelBuildingRequest
|
||||
import org.apache.maven.model.io.xpp3.MavenXpp3Reader
|
||||
import org.apache.maven.project.MavenProject
|
||||
@@ -37,6 +38,7 @@ import org.apache.maven.shared.filtering.DefaultMavenFileFilter
|
||||
import org.apache.maven.shared.filtering.DefaultMavenReaderFilter
|
||||
import org.apache.maven.shared.filtering.DefaultMavenResourcesFiltering
|
||||
import org.codehaus.plexus.logging.Logger
|
||||
import org.codehaus.plexus.util.xml.Xpp3Dom
|
||||
import org.codehaus.plexus.util.xml.Xpp3DomBuilder
|
||||
import org.eclipse.aether.impl.VersionRangeResolver
|
||||
import org.junit.AfterClass
|
||||
@@ -48,6 +50,8 @@ import org.sonatype.plexus.build.incremental.DefaultBuildContext
|
||||
import static groovy.test.GroovyAssert.shouldFail
|
||||
import static io.repaint.maven.tiles.Constants.TILEPLUGIN_ARTIFACT
|
||||
import static io.repaint.maven.tiles.Constants.TILEPLUGIN_GROUP
|
||||
import static io.repaint.maven.tiles.GavUtil.artifactName
|
||||
import static org.junit.Assert.assertEquals
|
||||
import static org.mockito.Mockito.mock
|
||||
import static org.mockito.Mockito.when
|
||||
|
||||
@@ -149,6 +153,69 @@ public class TilesMavenLifecycleParticipantTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTileMerge() {
|
||||
|
||||
Model model = new Model()
|
||||
model.setGroupId("io.repaint.tiles")
|
||||
model.setArtifactId("test-merge-tile")
|
||||
model.setVersion("1.1-SNAPSHOT")
|
||||
|
||||
model.build = new Build()
|
||||
model.build.directory = "target/test-merge-tile"
|
||||
|
||||
MavenProject project = new MavenProject(model)
|
||||
project.setFile(new File("src/test/resources/test-merge-tile/pom.xml"))
|
||||
|
||||
MavenExecutionRequest req = mock(MavenExecutionRequest.class)
|
||||
when(req.getUserProperties()).thenReturn(new Properties())
|
||||
when(req.getSystemProperties()).thenReturn(new Properties())
|
||||
|
||||
MavenSession session = new MavenSession(null, req, mock(MavenExecutionResult.class), Arrays.asList(project))
|
||||
|
||||
addUnprocessedTile('test-merge-tile/kapt-tile.xml', 'kapt-tile')
|
||||
addUnprocessedTile('test-merge-tile/kapt-dinject-tile.xml', 'kapt-dinject-tile')
|
||||
addUnprocessedTile('test-merge-tile/kapt-javalin-tile.xml', 'kapt-javalin-tile')
|
||||
|
||||
// act
|
||||
participant.loadAllDiscoveredTiles(session, project)
|
||||
|
||||
|
||||
Model tileModel = participant.processedTiles['io.repaint.tiles:kapt-tile'].tileModel.model
|
||||
PluginExecution pluginExecution = tileModel.build.plugins[0].executions[0]
|
||||
assert pluginExecution.id == 'kapt'
|
||||
|
||||
// assert properties have been merged
|
||||
assert tileModel.properties['dinject-generator.version'] == '1.8'
|
||||
assert tileModel.properties['kotlin.version'] == '1.3.31'
|
||||
|
||||
String expectedAnnotationProcessorPaths = '''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<annotationProcessorPaths>
|
||||
<annotationProcessorPath>
|
||||
<groupId>io.dinject</groupId>
|
||||
<artifactId>javalin-generator</artifactId>
|
||||
<version>1.6</version>
|
||||
</annotationProcessorPath>
|
||||
<annotationProcessorPath>
|
||||
<groupId>io.dinject</groupId>
|
||||
<artifactId>dinject-generator</artifactId>
|
||||
<version>${dinject-generator.version}</version>
|
||||
</annotationProcessorPath>
|
||||
</annotationProcessorPaths>
|
||||
'''.trim()
|
||||
|
||||
// assert the annotationProcessorPaths have been appended
|
||||
Xpp3Dom paths = ((Xpp3Dom)pluginExecution.configuration).getChild('annotationProcessorPaths')
|
||||
assertEquals(paths.toString().trim(), expectedAnnotationProcessorPaths)
|
||||
}
|
||||
|
||||
def addUnprocessedTile(String testResourceName, String tileName) {
|
||||
Artifact kaptTile = participant.turnPropertyIntoUnprocessedTile("io.repaint.tiles:$tileName:1.1", null)
|
||||
kaptTile.file = new File("src/test/resources/$testResourceName")
|
||||
participant.unprocessedTiles.put(artifactName(kaptTile), kaptTile)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFiltering() {
|
||||
final def context = new DefaultBuildContext()
|
||||
|
41
src/test/resources/test-merge-tile/kapt-dinject-tile.xml
Normal file
41
src/test/resources/test-merge-tile/kapt-dinject-tile.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project>
|
||||
|
||||
<description>
|
||||
Add KAPT annotation processor to generate DInject Dependency injection (as java source code).
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<dinject-generator.version>1.8</dinject-generator.version>
|
||||
<tile-merge-source>true</tile-merge-source>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>kapt</id>
|
||||
<configuration tiles-keep-id="true">
|
||||
<annotationProcessorPaths>
|
||||
<annotationProcessorPath>
|
||||
<groupId>io.dinject</groupId>
|
||||
<artifactId>dinject-generator</artifactId>
|
||||
<version>${dinject-generator.version}</version>
|
||||
</annotationProcessorPath>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
</project>
|
41
src/test/resources/test-merge-tile/kapt-javalin-tile.xml
Normal file
41
src/test/resources/test-merge-tile/kapt-javalin-tile.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project>
|
||||
|
||||
<description>
|
||||
Add KAPT annotation processor to generate javalin controllers (as java source code).
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<tile-merge-source>true</tile-merge-source>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>kapt</id>
|
||||
<configuration tiles-keep-id="true">
|
||||
<annotationProcessorPaths>
|
||||
<annotationProcessorPath>
|
||||
<!-- Generate web route adapters for Javalin Controllers -->
|
||||
<groupId>io.dinject</groupId>
|
||||
<artifactId>javalin-generator</artifactId>
|
||||
<version>1.6</version>
|
||||
</annotationProcessorPath>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
</project>
|
114
src/test/resources/test-merge-tile/kapt-tile.xml
Normal file
114
src/test/resources/test-merge-tile/kapt-tile.xml
Normal file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project>
|
||||
|
||||
<description>
|
||||
Kotlin compiler with KAPT annotation processing support.
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<tile-merge-target>true</tile-merge-target>
|
||||
<java.version>1.8</java.version>
|
||||
<kotlin.version>1.3.31</kotlin.version>
|
||||
<kotlin.apiVersion>1.3</kotlin.apiVersion>
|
||||
<kotlin.jvmTarget>1.8</kotlin.jvmTarget>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
|
||||
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<configuration>
|
||||
<apiVersion>${kotlin.apiVersion}</apiVersion>
|
||||
<jvmTarget>${kotlin.jvmTarget}</jvmTarget>
|
||||
</configuration>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>kapt</id>
|
||||
<goals>
|
||||
<goal>kapt</goal>
|
||||
</goals>
|
||||
<configuration tiles-keep-id="true" tiles-append="annotationProcessorPaths">
|
||||
<sourceDirs>
|
||||
<sourceDir>src/main/kotlin</sourceDir>
|
||||
<sourceDir>src/main/java</sourceDir>
|
||||
</sourceDirs>
|
||||
<annotationProcessorPaths>
|
||||
|
||||
<!-- annotation processors added here -->
|
||||
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<configuration tiles-keep-id="true"/>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<configuration tiles-keep-id="true"/>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
<executions>
|
||||
<!-- Replacing default-compile as it is treated specially by maven -->
|
||||
<execution>
|
||||
<id>default-compile</id>
|
||||
<phase>none</phase>
|
||||
<configuration tiles-keep-id="true"/>
|
||||
</execution>
|
||||
<!-- Replacing default-testCompile as it is treated specially by maven -->
|
||||
<execution>
|
||||
<id>default-testCompile</id>
|
||||
<phase>none</phase>
|
||||
<configuration tiles-keep-id="true"/>
|
||||
</execution>
|
||||
<execution>
|
||||
<configuration tiles-keep-id="true"/>
|
||||
<id>java-compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<configuration tiles-keep-id="true"/>
|
||||
<id>java-test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
</project>
|
33
src/test/resources/test-merge-tile/pom.xml
Normal file
33
src/test/resources/test-merge-tile/pom.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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. See accompanying LICENSE file.
|
||||
-->
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>io.repaint.tiles</groupId>
|
||||
<artifactId>test-tile-merge</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<packaging>tile</packaging>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.repaint.maven</groupId>
|
||||
<artifactId>tiles-maven-plugin</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<extensions>true</extensions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
Reference in New Issue
Block a user