IDEA-169130 maven - ability to resolve local properties in modules's parent definition while building, this way we're able to actually reimport such modules

This commit is contained in:
Ivan Bessonov
2017-04-05 18:57:42 +03:00
parent 687a21acfb
commit c2d55a0039
9 changed files with 204 additions and 13 deletions

View File

@@ -15,6 +15,7 @@
*/
package org.jetbrains.idea.maven.server.embedder;
import com.intellij.util.containers.ContainerUtil;
import org.apache.maven.model.Model;
import org.apache.maven.project.ProjectBuilderConfiguration;
import org.apache.maven.project.interpolation.ModelInterpolationException;
@@ -31,12 +32,21 @@ public class CustomMaven3ModelInterpolator extends StringSearchModelInterpolator
super(pathTranslator);
}
@Override
public Model interpolate(Model model, File projectDir, ProjectBuilderConfiguration config, boolean debugEnabled)
throws ModelInterpolationException {
this.interpolateObject(ContainerUtil.ar(model.getParent(), model), model, projectDir, config, debugEnabled);
return model;
}
@Override
protected void interpolateObject(Object obj,
Model model,
File projectDir,
ProjectBuilderConfiguration config,
boolean debugEnabled) throws ModelInterpolationException {
if (obj == null) return;
// IDEA-74131 avoid concurrent access to the static cache in StringSearchModelInterpolator
synchronized (CustomMaven3ModelInterpolator.class) {
try {

View File

@@ -35,6 +35,11 @@ public class CustomMaven3ModelInterpolator2 extends StringSearchModelInterpolato
private String localRepository;
@Override
public void interpolateObject(Object obj, Model model, File projectDir, ModelBuildingRequest config, ModelProblemCollector problems) {
super.interpolateObject(obj, model, projectDir, config, problems);
}
@Override
protected List<ValueSource> createValueSources(Model model,
File projectDir,

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* 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 org.jetbrains.idea.maven.server.embedder;
import org.apache.maven.model.InputLocation;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.building.ModelProblemCollector;
import org.apache.maven.model.interpolation.ModelInterpolator;
import org.apache.maven.model.validation.DefaultModelValidator;
import org.apache.maven.model.validation.ModelValidator;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import static com.intellij.openapi.util.text.StringUtil.notNullize;
/**
* @author ibessonov
*/
@Component(role = ModelValidator.class, hint = "ide")
public class CustomModelValidator extends DefaultModelValidator {
@Requirement(role = ModelInterpolator.class)
private CustomMaven3ModelInterpolator2 myModelInterpolator;
@Override
public void validateRawModel(Model model, ModelBuildingRequest request, ModelProblemCollector problems) {
ProxyModelProblemCollector problemsProxy = new ProxyModelProblemCollector(problems);
super.validateRawModel(model, request, problemsProxy);
Parent parent = model.getParent();
if (parent != null && !problemsProxy.hasFatalErrors()) {
if (parent.getGroupId().contains("${") || parent.getArtifactId().contains("${") || parent.getVersion().contains("${")) {
myModelInterpolator.interpolateObject(parent, model, model.getProjectDirectory(), request, problems);
if (equals(parent.getGroupId(), model.getGroupId()) && equals(parent.getArtifactId(), model.getArtifactId())) {
try {
// will encounter validation problem right on the start
super.validateRawModel(model, request, new AbortOnFirstErrorProblemsCollector(problems));
}
catch (AbortOnErrorException ignored) {
}
}
}
}
}
private static boolean equals(String a, String b) {
return notNullize(a).equals(notNullize(b));
}
private static class ProxyModelProblemCollector implements ModelProblemCollector {
private final ModelProblemCollector myDelegate;
private boolean myHasFatalErrors = false;
public ProxyModelProblemCollector(ModelProblemCollector delegate) {
myDelegate = delegate;
}
@Override
public void add(ModelProblem.Severity severity, String s, InputLocation location, Exception e) {
myHasFatalErrors |= (severity == ModelProblem.Severity.FATAL);
myDelegate.add(severity, s, location, e);
}
public boolean hasFatalErrors() {
return myHasFatalErrors;
}
}
private static class AbortOnErrorException extends RuntimeException {
}
private static class AbortOnFirstErrorProblemsCollector extends ProxyModelProblemCollector {
public AbortOnFirstErrorProblemsCollector(ModelProblemCollector delegate) {
super(delegate);
}
@Override
public void add(ModelProblem.Severity severity, String s, InputLocation location, Exception e) {
super.add(severity, s, location, e);
throw new AbortOnErrorException();
}
}
}

View File

@@ -111,6 +111,13 @@
<isolated-realm>false</isolated-realm>
</component>
<component>
<role>org.apache.maven.model.validation.ModelValidator</role>
<role-hint>ide</role-hint>
<implementation>org.jetbrains.idea.maven.server.embedder.CustomModelValidator</implementation>
<description/>
<isolated-realm>false</isolated-realm>
</component>
</components>
</component-set>

View File

@@ -43,12 +43,11 @@ import org.apache.maven.model.Activation;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.Profile;
import org.apache.maven.model.building.FileModelSource;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.building.ModelProcessor;
import org.apache.maven.model.building.*;
import org.apache.maven.model.interpolation.ModelInterpolator;
import org.apache.maven.model.io.ModelReader;
import org.apache.maven.model.profile.DefaultProfileInjector;
import org.apache.maven.model.validation.ModelValidator;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.plugin.PluginDescriptorCache;
import org.apache.maven.plugin.internal.PluginDependenciesResolver;
@@ -117,6 +116,7 @@ import java.util.*;
* <p/>
* maven-model-builder:
* org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator2 <-> org.apache.maven.model.interpolation.StringSearchModelInterpolator
* org.jetbrains.idea.maven.server.embedder.CustomModelValidator <-> org.apache.maven.model.validation.ModelValidator
*/
public class Maven3ServerEmbedderImpl extends Maven3ServerEmbedder {
@@ -552,9 +552,16 @@ public class Maven3ServerEmbedderImpl extends Maven3ServerEmbedder {
myContainer.addComponent(getComponent(ArtifactResolver.class, "ide"), ArtifactResolver.ROLE);
myContainer.addComponent(getComponent(RepositoryMetadataManager.class, "ide"), RepositoryMetadataManager.class.getName());
myContainer.addComponent(getComponent(PluginDescriptorCache.class, "ide"), PluginDescriptorCache.class.getName());
myContainer.addComponent(getComponent(ModelInterpolator.class, "ide"), ModelInterpolator.class.getName());
ModelInterpolator modelInterpolator = getComponent(ModelInterpolator.class, "ide");
myContainer.addComponent(modelInterpolator, ModelInterpolator.class.getName());
myContainer.addComponent(getComponent(org.apache.maven.project.interpolation.ModelInterpolator.class, "ide"),
org.apache.maven.project.interpolation.ModelInterpolator.ROLE);
ModelValidator modelValidator = getComponent(ModelValidator.class, "ide");
myContainer.addComponent(modelValidator, ModelValidator.class.getName());
DefaultModelBuilder defaultModelBuilder = (DefaultModelBuilder)getComponent(ModelBuilder.class);
defaultModelBuilder.setModelValidator(modelValidator);
defaultModelBuilder.setModelInterpolator(modelInterpolator);
}
private void setConsoleAndIndicator(MavenServerConsole console, MavenServerProgressIndicator indicator) {

View File

@@ -111,6 +111,13 @@
<isolated-realm>false</isolated-realm>
</component>
<component>
<role>org.apache.maven.model.validation.ModelValidator</role>
<role-hint>ide</role-hint>
<implementation>org.jetbrains.idea.maven.server.embedder.CustomModelValidator</implementation>
<description/>
<isolated-realm>false</isolated-realm>
</component>
</components>
</component-set>

View File

@@ -39,9 +39,12 @@ import org.apache.maven.model.Activation;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.Profile;
import org.apache.maven.model.building.DefaultModelBuilder;
import org.apache.maven.model.building.ModelBuilder;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.interpolation.ModelInterpolator;
import org.apache.maven.model.profile.DefaultProfileInjector;
import org.apache.maven.model.validation.ModelValidator;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.plugin.PluginDescriptorCache;
import org.apache.maven.plugin.internal.PluginDependenciesResolver;
@@ -104,6 +107,7 @@ import java.util.*;
* <p/>
* maven-model-builder:
* org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator2 <-> org.apache.maven.model.interpolation.StringSearchModelInterpolator
* org.jetbrains.idea.maven.server.embedder.CustomModelValidator <-> org.apache.maven.model.validation.ModelValidator
*/
public class Maven30ServerEmbedderImpl extends Maven3ServerEmbedder {
@@ -516,9 +520,16 @@ public class Maven30ServerEmbedderImpl extends Maven3ServerEmbedder {
myContainer.addComponent(getComponent(ArtifactResolver.class, "ide"), ArtifactResolver.ROLE);
myContainer.addComponent(getComponent(RepositoryMetadataManager.class, "ide"), RepositoryMetadataManager.class.getName());
myContainer.addComponent(getComponent(PluginDescriptorCache.class, "ide"), PluginDescriptorCache.class.getName());
myContainer.addComponent(getComponent(ModelInterpolator.class, "ide"), ModelInterpolator.class.getName());
ModelInterpolator modelInterpolator = getComponent(ModelInterpolator.class, "ide");
myContainer.addComponent(modelInterpolator, ModelInterpolator.class.getName());
myContainer.addComponent(getComponent(org.apache.maven.project.interpolation.ModelInterpolator.class, "ide"),
org.apache.maven.project.interpolation.ModelInterpolator.ROLE);
ModelValidator modelValidator = getComponent(ModelValidator.class, "ide");
myContainer.addComponent(modelValidator, ModelValidator.class.getName());
DefaultModelBuilder defaultModelBuilder = (DefaultModelBuilder)getComponent(ModelBuilder.class);
defaultModelBuilder.setModelValidator(modelValidator);
defaultModelBuilder.setModelInterpolator(modelInterpolator);
}
private void setConsoleAndIndicator(MavenServerConsole console, MavenServerProgressIndicator indicator) {

View File

@@ -125,6 +125,9 @@ public class MavenProject {
MavenModel model = readerResult.mavenModel;
newState.myMavenId = model.getMavenId();
if (model.getParent() != null) {
newState.myParentId = model.getParent().getMavenId();
}
newState.myPackaging = model.getPackaging();
newState.myName = model.getName();
@@ -144,14 +147,6 @@ public class MavenProject {
doSetResolvedAttributes(newState, readerResult, resetArtifacts);
MavenModelPropertiesPatcher.patch(newState.myProperties, newState.myPlugins);
if (model.getParent() != null) {
MavenId parentId = model.getParent().getMavenId();
newState.myParentId = new MavenId(
MavenUtil.expandProperties(parentId.getGroupId(), newState.myProperties),
MavenUtil.expandProperties(parentId.getArtifactId(), newState.myProperties),
MavenUtil.expandProperties(parentId.getVersion(), newState.myProperties)
);
}
newState.myModulesPathsAndNames = collectModulePathsAndNames(model, getDirectory());
Collection<String> newProfiles = collectProfilesIds(model.getProfiles());

View File

@@ -402,4 +402,51 @@ public class ReimportingTest extends MavenImportingTestCase {
assertEquals("1.7", compilerConfiguration.getBytecodeTargetLevel(getModule("project")));
assertEquals("1.7", compilerConfiguration.getBytecodeTargetLevel(getModule("m1")));
}
public void testParentVersionProperty2() throws Exception {
createProjectPom("<groupId>test</groupId>\n" +
"<artifactId>project</artifactId>\n" +
"<version>1</version>\n" +
"<modules>\n" +
" <module>m1</module>\n" +
"</modules>");
String m1pomTemplate = "<parent>\n" +
" <groupId>${my.parent.groupId}</groupId>\n" +
" <artifactId>project</artifactId>\n" +
" <version>${my.parent.version}</version>\n" +
"</parent>\n" +
"<artifactId>m1</artifactId>\n" +
"<version>${my.parent.version}</version>\n" +
"<properties>\n" +
" <my.parent.version>1</my.parent.version>\n" +
" <my.parent.groupId>test</my.parent.groupId>\n" +
"</properties>\n" +
"<build>\n" +
" <plugins>\n" +
" <plugin>\n" +
" <artifactId>maven-compiler-plugin</artifactId>\n" +
" <version>3.1</version>\n" +
" <configuration>\n" +
" <source>%s</source>\n" +
" <target>%<s</target>\n" +
" </configuration>\n" +
" </plugin>\n" +
" </plugins>\n" +
"</build>";
createModulePom("m1", String.format(m1pomTemplate, "1.8"));
CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(myProject);
configConfirmationForYesAnswer();
importProjectWithMaven3();
assertEquals(LanguageLevel.JDK_1_8, getEffectiveLanguageLevel(getModule("m1")));
assertEquals("1.8", compilerConfiguration.getBytecodeTargetLevel(getModule("m1")));
createModulePom("m1", String.format(m1pomTemplate, "1.7"));
importProjectWithMaven3();
assertEquals(LanguageLevel.JDK_1_7, getEffectiveLanguageLevel(getModule("m1")));
assertEquals("1.7", compilerConfiguration.getBytecodeTargetLevel(getModule("m1")));
}
}