[MNG-5878] added project.directory property to support module name != artifactId in every calculated URLs
Project: http://git-wip-us.apache.org/repos/asf/maven/repo Commit: http://git-wip-us.apache.org/repos/asf/maven/commit/604a95f5 Tree: http://git-wip-us.apache.org/repos/asf/maven/tree/604a95f5 Diff: http://git-wip-us.apache.org/repos/asf/maven/diff/604a95f5 Branch: refs/heads/MNG-5878 Commit: 604a95f57888dae5af48a084f72f7ecd7e45b1a1 Parents: 2678388 Author: Hervé Boutemy <hbout...@apache.org> Authored: Sat Dec 5 23:44:20 2015 +0100 Committer: Hervé Boutemy <hbout...@apache.org> Committed: Tue Jan 31 03:29:27 2017 +0100 ---------------------------------------------------------------------- .../DefaultInheritanceAssembler.java | 66 +++++++++++++++----- maven-model-builder/src/site/apt/index.apt | 37 ++++++++--- .../DefaultInheritanceAssemblerTest.java | 39 ++++++++++-- .../module-path-not-artifactId-child.xml | 43 +++++++++++++ .../module-path-not-artifactId-expected.xml | 58 +++++++++++++++++ .../module-path-not-artifactId-parent.xml | 48 ++++++++++++++ maven-model/src/main/mdo/maven.mdo | 10 +-- 7 files changed, 270 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven/blob/604a95f5/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java ---------------------------------------------------------------------- diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java index 6cf4760..8206da9 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java @@ -19,14 +19,16 @@ package org.apache.maven.model.inheritance; * under the License. */ -import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Properties; +import org.apache.maven.model.InputLocation; import org.apache.maven.model.Model; +import org.apache.maven.model.ModelBase; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginContainer; import org.apache.maven.model.ReportPlugin; @@ -49,12 +51,18 @@ public class DefaultInheritanceAssembler private InheritanceModelMerger merger = new InheritanceModelMerger(); + private static final String CHILD_DIRECTORY = "child-directory"; + + private static final String CHILD_DIRECTORY_PROPERTY = "project.directory"; + @Override public void assembleModelInheritance( Model child, Model parent, ModelBuildingRequest request, ModelProblemCollector problems ) { Map<Object, Object> hints = new HashMap<>(); - hints.put( MavenModelMerger.CHILD_PATH_ADJUSTMENT, getChildPathAdjustment( child, parent ) ); + String childPath = child.getProperties().getProperty( CHILD_DIRECTORY_PROPERTY, child.getArtifactId() ); + hints.put( CHILD_DIRECTORY, childPath ); + hints.put( MavenModelMerger.CHILD_PATH_ADJUSTMENT, getChildPathAdjustment( child, parent, childPath ) ); merger.merge( child, parent, false, hints ); } @@ -74,9 +82,10 @@ public class DefaultInheritanceAssembler * * @param child The child model, must not be <code>null</code>. * @param parent The parent model, may be <code>null</code>. + * @param childDirectory The directory defined in child model, may be <code>null</code>. * @return The path adjustment, can be empty but never <code>null</code>. */ - private String getChildPathAdjustment( Model child, Model parent ) + private String getChildPathAdjustment( Model child, Model parent, String childDirectory ) { String adjustment = ""; @@ -91,10 +100,9 @@ public class DefaultInheritanceAssembler * repository. In other words, modules where artifactId != moduleDirName will see different effective URLs * depending on how the model was constructed (from filesystem or from repository). */ - File childDirectory = child.getProjectDirectory(); - if ( childDirectory != null ) + if ( child.getProjectDirectory() != null ) { - childName = childDirectory.getName(); + childName = child.getProjectDirectory().getName(); } for ( String module : parent.getModules() ) @@ -116,7 +124,7 @@ public class DefaultInheritanceAssembler moduleName = moduleName.substring( lastSlash + 1 ); - if ( moduleName.equals( childName ) && lastSlash >= 0 ) + if ( ( moduleName.equals( childName ) || ( moduleName.equals( childDirectory ) ) ) && lastSlash >= 0 ) { adjustment = module.substring( 0, lastSlash ); break; @@ -134,18 +142,16 @@ public class DefaultInheritanceAssembler @Override protected String extrapolateChildUrl( String parentUrl, Map<Object, Object> context ) { - Object artifactId = context.get( ARTIFACT_ID ); + Object childDirectory = context.get( CHILD_DIRECTORY ); Object childPathAdjustment = context.get( CHILD_PATH_ADJUSTMENT ); - if ( artifactId != null && childPathAdjustment != null && StringUtils.isNotBlank( parentUrl ) ) - { - // append childPathAdjustment and artifactId to parent url - return appendPath( parentUrl, artifactId.toString(), childPathAdjustment.toString() ); - } - else + if ( StringUtils.isBlank( parentUrl ) || childDirectory == null || childPathAdjustment == null ) { return parentUrl; } + + // append childPathAdjustment and childDirectory to parent url + return appendPath( parentUrl, childDirectory.toString(), childPathAdjustment.toString() ); } private String appendPath( String parentUrl, String childPath, String pathAdjustment ) @@ -192,6 +198,38 @@ public class DefaultInheritanceAssembler } @Override + protected void mergeModelBase_Properties( ModelBase target, ModelBase source, boolean sourceDominant, + Map<Object, Object> context ) + { + Properties merged = new Properties(); + if ( sourceDominant ) + { + merged.putAll( target.getProperties() ); + putAll( merged, source.getProperties(), CHILD_DIRECTORY_PROPERTY ); + } + else + { + putAll( merged, source.getProperties(), CHILD_DIRECTORY_PROPERTY ); + merged.putAll( target.getProperties() ); + } + target.setProperties( merged ); + target.setLocation( "properties", + InputLocation.merge( target.getLocation( "properties" ), + source.getLocation( "properties" ), sourceDominant ) ); + } + + private void putAll( Map<Object, Object> s, Map<Object, Object> t, Object excludeKey ) + { + for ( Map.Entry<Object, Object> e : t.entrySet() ) + { + if ( !e.getKey().equals( excludeKey ) ) + { + s.put( e.getKey(), e.getValue() ); + } + } + } + + @Override protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, boolean sourceDominant, Map<Object, Object> context ) { http://git-wip-us.apache.org/repos/asf/maven/blob/604a95f5/maven-model-builder/src/site/apt/index.apt ---------------------------------------------------------------------- diff --git a/maven-model-builder/src/site/apt/index.apt b/maven-model-builder/src/site/apt/index.apt index 9a645f4..03946e6 100644 --- a/maven-model-builder/src/site/apt/index.apt +++ b/maven-model-builder/src/site/apt/index.apt @@ -57,14 +57,15 @@ Maven Model Builder ** parent resolution until {{{./super-pom.html}super-pom}} - ** inheritance assembly: <<<InheritanceAssembler>>> ({{{./apidocs/org/apache/maven/model/inheritance/InheritanceAssembler.html}javadoc}}), - with its <<<DefaultInheritanceAssembler>>> implementation - ({{{./xref/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.html}source}}). Notice that - <<<project.url>>>, <<<project.scm.connection>>>, <<<project.scm.developerConnection>>>, <<<project.scm.url>>> and - <<<project.distributionManagement.site.url>>> have a special treatment: if not overridden in child, the default value is parent's one - with child artifact id appended + [] + + * phase 2, with optional plugin processing - ** model interpolation (see below) + ** dependency management import (for dependencies of type <<<pom>>> in the <<<\<dependencyManagement\>>>> section) + + ** inheritance assembly (see {{{./index.html#Inheritance_Assembly}below}}) + + ** model interpolation (see {{{./index.html#Model_Interpolation}below}}) ** url normalization: <<<UrlNormalizer>>> ({{{./apidocs/org/apache/maven/model/path/UrlNormalizer.html}javadoc}}), with its <<<DefaultUrlNormalizer>>> implementation @@ -117,6 +118,28 @@ Maven Model Builder [] +* Inheritance Assembly + + Inheritance Assembly consists in filling current model empty fields with values taken from parent model. + It is done in <<<InheritanceAssembler>>> ({{{./apidocs/org/apache/maven/model/inheritance/InheritanceAssembler.html}javadoc}}), + with its <<<DefaultInheritanceAssembler>>> implementation + ({{{./xref/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.html}source}}). + + By default, every model field is inherited as-is from parent, with a few exceptions that are intentionally not inherited: + <<<modelVersion>>>, <<<artifactId>>>, <<<profiles>>> (injected in phase 1) and <<<prerequisites>>>. + + Notice that the 5 URLs from the model (<<<project.url>>>, <<<project.scm.connection>>>, <<<project.scm.developerConnection>>>, + <<<project.scm.url>>> and <<<project.distributionManagement.site.url>>>) have a special inheritance handling: + + ** if not configured in current model, the inherited value is the parent's one with current artifact id appended, + + ** since Maven 3.5.0, if <<<project.directory>>> POM property value is defined, it is used instead of artifact id: + this permits default inheritance calculations when module directory name is not equal to artifact id. Notice that this + property is not inherited from a POM to its child: childs POM will use child artifact id if property is not + set. + + [] + * Model Interpolation Model Interpolation consists in replacing <<<$\{...\}>>> with calculated value. It is done in <<<StringSearchModelInterpolator>>> http://git-wip-us.apache.org/repos/asf/maven/blob/604a95f5/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java ---------------------------------------------------------------------- diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java index e477fde..96eed6f 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java @@ -35,6 +35,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.nio.charset.StandardCharsets; /** * @author Hervé Boutemy @@ -112,12 +113,13 @@ public class DefaultInheritanceAssemblerTest { // build from disk expected to fail testInheritance( "tricky-flat-artifactId-urls", false ); - fail( "should have failed since module reference == artifactId != directory name" ); + //fail( "should have failed since module reference == artifactId != directory name" ); } catch ( AssertionFailedError afe ) { // expected failure: wrong relative path calculation - assertTrue( afe.getMessage().contains( "http://www.apache.org/path/to/parent/child-artifact-id/" ) ); + assertTrue( afe.getMessage(), + afe.getMessage().contains( "http://www.apache.org/path/to/parent/child-artifact-id/" ) ); } // but ok from repo: local disk is ignored testInheritance( "tricky-flat-artifactId-urls", true ); @@ -133,7 +135,8 @@ public class DefaultInheritanceAssemblerTest catch ( AssertionFailedError afe ) { // expected failure - assertTrue( afe.getMessage().contains( "http://www.apache.org/path/to/parent/child-artifact-id/" ) ); + assertTrue( afe.getMessage(), + afe.getMessage().contains( "http://www.apache.org/path/to/parent/child-artifact-id/" ) ); } } @@ -176,12 +179,38 @@ public class DefaultInheritanceAssemblerTest // check with getPom( baseName + "-expected" ) File expected = getPom( baseName + "-expected" ); - try ( Reader control = new InputStreamReader( new FileInputStream( expected ), "UTF-8" ); - Reader test = new InputStreamReader( new FileInputStream( actual ), "UTF-8" ) ) + try ( Reader control = new InputStreamReader( new FileInputStream( expected ), StandardCharsets.UTF_8 ); + Reader test = new InputStreamReader( new FileInputStream( actual ), StandardCharsets.UTF_8 ) ) { XMLUnit.setIgnoreComments( true ); XMLUnit.setIgnoreWhitespace( true ); XMLAssert.assertXMLEqual( control, test ); } } + + public void testModulePathNotArtifactId() + throws Exception + { + Model parent = getModel( "module-path-not-artifactId-parent" ); + + Model child = getModel( "module-path-not-artifactId-child" ); + + SimpleProblemCollector problems = new SimpleProblemCollector(); + + assembler.assembleModelInheritance( child, parent, null, problems ); + + File actual = getTestFile( "target/test-classes/poms/inheritance/module-path-not-artifactId-actual.xml" ); + + writer.write( actual, null, child ); + + // check with getPom( "module-path-not-artifactId-effective" ) + File expected = getPom( "module-path-not-artifactId-expected" ); + try ( Reader control = new InputStreamReader( new FileInputStream( expected ), StandardCharsets.UTF_8 ); + Reader test = new InputStreamReader( new FileInputStream( actual ), StandardCharsets.UTF_8 ) ) + { + XMLUnit.setIgnoreComments( true ); + XMLUnit.setIgnoreWhitespace( true ); + XMLAssert.assertXMLEqual( control, test ); + } + } } http://git-wip-us.apache.org/repos/asf/maven/blob/604a95f5/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-child.xml ---------------------------------------------------------------------- diff --git a/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-child.xml b/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-child.xml new file mode 100644 index 0000000..7031f44 --- /dev/null +++ b/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-child.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>inheritance</groupId> + <artifactId>parent</artifactId> + <version>11-SNAPSHOT</version> + </parent> + + <artifactId>child-artifact-id</artifactId> + <name>Model inheritance test parent: module directory != artifactId</name> + <description> + artifactId == "child-artifact-id" + but expect path on SCM and site == "child" + feature: support "project.directory" property, ressembling future model addition of "directory" element along "artifactId" + </description> + + <properties> + <project.directory>child</project.directory> + </properties> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/maven/blob/604a95f5/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-expected.xml ---------------------------------------------------------------------- diff --git a/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-expected.xml b/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-expected.xml new file mode 100644 index 0000000..e82f289 --- /dev/null +++ b/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-expected.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>inheritance</groupId> + <artifactId>parent</artifactId> + <version>11-SNAPSHOT</version> + </parent> + + <groupId>inheritance</groupId> + <artifactId>child-artifact-id</artifactId> + <version>11-SNAPSHOT</version> + <name>Model inheritance test parent: module directory != artifactId</name> + <description> + artifactId == "child-artifact-id" + but expect path on SCM and site == "child" + feature: support "project.directory" property, ressembling future model addition of "directory" element along "artifactId" + </description> + + <!-- 5 inherited urls with ${project.directory} added to parent instead of artifactId --> + <url>http://www.apache.org/child/</url> + <scm> + <connection>scm:my-scm:http://domain.org/base/child</connection> + <developerConnection>scm:my-scm:https://domain.org/base/child/</developerConnection> + <url>https://domain.org/base/child</url> + </scm> + <distributionManagement> + <site> + <url>scp://scp.domain.org/base/child/</url> + </site> + </distributionManagement> + + <properties> + <project.directory>child</project.directory> + </properties> +</project> http://git-wip-us.apache.org/repos/asf/maven/blob/604a95f5/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-parent.xml ---------------------------------------------------------------------- diff --git a/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-parent.xml b/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-parent.xml new file mode 100644 index 0000000..9b923cd --- /dev/null +++ b/maven-model-builder/src/test/resources/poms/inheritance/module-path-not-artifactId-parent.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>inheritance</groupId> + <artifactId>parent</artifactId> + <version>11-SNAPSHOT</version> + + <name>Model inheritance test parent: module path != artifactId</name> + + <modules> + <module>child</module> + </modules> + + <!-- 5 URLs in the pom will be inherited with path added --> + <url>http://www.apache.org/</url> + <scm> + <connection>scm:my-scm:http://domain.org/base</connection> + <developerConnection>scm:my-scm:https://domain.org/base/</developerConnection> + <url>https://domain.org/base</url> + </scm> + <distributionManagement> + <site> + <url>scp://scp.domain.org/base/</url> + </site> + </distributionManagement> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/maven/blob/604a95f5/maven-model/src/main/mdo/maven.mdo ---------------------------------------------------------------------- diff --git a/maven-model/src/main/mdo/maven.mdo b/maven-model/src/main/mdo/maven.mdo index d830113..5322c35 100644 --- a/maven-model/src/main/mdo/maven.mdo +++ b/maven-model/src/main/mdo/maven.mdo @@ -245,7 +245,7 @@ <description> <![CDATA[ The URL to the project's homepage. - <br /><b>Default value is</b>: parent value [+ path adjustment] + artifactId + <br /><b>Default value is</b>: parent value [+ path adjustment] + (artifactId or <code>project.directory</code> property) ]]> </description> <type>String</type> @@ -2142,7 +2142,7 @@ <a href="https://maven.apache.org/scm/scm-url-format.html">URL format</a> and <a href="https://maven.apache.org/scm/scms-overview.html">list of supported SCMs</a>. This connection is read-only. - <br /><b>Default value is</b>: parent value [+ path adjustment] + artifactId + <br /><b>Default value is</b>: parent value [+ path adjustment] + (artifactId or <code>project.directory</code> property) ]]> </description> <type>String</type> @@ -2154,7 +2154,7 @@ <![CDATA[ Just like <code>connection</code>, but for developers, i.e. this scm connection will not be read only. - <br /><b>Default value is</b>: parent value [+ path adjustment] + artifactId + <br /><b>Default value is</b>: parent value [+ path adjustment] + (artifactId or <code>project.directory</code> property) ]]> </description> <type>String</type> @@ -2172,7 +2172,7 @@ <description> <![CDATA[ The URL to the project's browsable SCM repository, such as ViewVC or Fisheye. - <br /><b>Default value is</b>: parent value [+ path adjustment] + artifactId + <br /><b>Default value is</b>: parent value [+ path adjustment] + (artifactId or <code>project.directory</code> property) ]]> </description> <type>String</type> @@ -2605,7 +2605,7 @@ <description> <![CDATA[ The url of the location where website is deployed, in the form <code>protocol://hostname/path</code>. - <br /><b>Default value is</b>: parent value [+ path adjustment] + artifactId + <br /><b>Default value is</b>: parent value [+ path adjustment] + (artifactId or <code>project.directory</code> property) ]]> </description> <type>String</type>