[MNG-6802] FileProfileActivator changes FileProfileActivator.exists which lets flattened resolveCiFriendliesOnly depending fail activating profile

Cherry picked from 3fabb639a3

This closes #649
This commit is contained in:
Ravil Galeyev 2021-05-15 13:51:15 +02:00 committed by Michael Osipov
parent 05b748ff6a
commit 0f3c39b8ed
6 changed files with 354 additions and 58 deletions

View File

@ -24,6 +24,7 @@ import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.model.Activation; import org.apache.maven.model.Activation;
import org.apache.maven.model.ActivationFile;
import org.apache.maven.model.Build; import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency; import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement; import org.apache.maven.model.DependencyManagement;
@ -46,11 +47,13 @@ import org.apache.maven.model.management.PluginManagementInjector;
import org.apache.maven.model.normalization.ModelNormalizer; import org.apache.maven.model.normalization.ModelNormalizer;
import org.apache.maven.model.path.ModelPathTranslator; import org.apache.maven.model.path.ModelPathTranslator;
import org.apache.maven.model.path.ModelUrlNormalizer; import org.apache.maven.model.path.ModelUrlNormalizer;
import org.apache.maven.model.path.ProfileActivationFilePathInterpolator;
import org.apache.maven.model.plugin.LifecycleBindingsInjector; import org.apache.maven.model.plugin.LifecycleBindingsInjector;
import org.apache.maven.model.plugin.PluginConfigurationExpander; import org.apache.maven.model.plugin.PluginConfigurationExpander;
import org.apache.maven.model.plugin.ReportConfigurationExpander; import org.apache.maven.model.plugin.ReportConfigurationExpander;
import org.apache.maven.model.plugin.ReportingConverter; import org.apache.maven.model.plugin.ReportingConverter;
import org.apache.maven.model.profile.DefaultProfileActivationContext; import org.apache.maven.model.profile.DefaultProfileActivationContext;
import org.apache.maven.model.profile.ProfileActivationContext;
import org.apache.maven.model.profile.ProfileInjector; import org.apache.maven.model.profile.ProfileInjector;
import org.apache.maven.model.profile.ProfileSelector; import org.apache.maven.model.profile.ProfileSelector;
import org.apache.maven.model.resolution.InvalidRepositoryException; import org.apache.maven.model.resolution.InvalidRepositoryException;
@ -59,8 +62,10 @@ import org.apache.maven.model.resolution.UnresolvableModelException;
import org.apache.maven.model.resolution.WorkspaceModelResolver; import org.apache.maven.model.resolution.WorkspaceModelResolver;
import org.apache.maven.model.superpom.SuperPomProvider; import org.apache.maven.model.superpom.SuperPomProvider;
import org.apache.maven.model.validation.ModelValidator; import org.apache.maven.model.validation.ModelValidator;
import org.codehaus.plexus.interpolation.InterpolationException;
import org.codehaus.plexus.interpolation.MapBasedValueSource; import org.codehaus.plexus.interpolation.MapBasedValueSource;
import org.codehaus.plexus.interpolation.StringSearchInterpolator; import org.codehaus.plexus.interpolation.StringSearchInterpolator;
import org.codehaus.plexus.util.StringUtils;
import org.eclipse.sisu.Nullable; import org.eclipse.sisu.Nullable;
import java.io.File; import java.io.File;
@ -142,6 +147,9 @@ public class DefaultModelBuilder
@Inject @Inject
private ReportingConverter reportingConverter; private ReportingConverter reportingConverter;
@Inject
private ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
public DefaultModelBuilder setModelProcessor( ModelProcessor modelProcessor ) public DefaultModelBuilder setModelProcessor( ModelProcessor modelProcessor )
{ {
this.modelProcessor = modelProcessor; this.modelProcessor = modelProcessor;
@ -244,6 +252,13 @@ public class DefaultModelBuilder
return this; return this;
} }
public DefaultModelBuilder setProfileActivationFilePathInterpolator(
ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator )
{
this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator;
return this;
}
@SuppressWarnings( "checkstyle:methodlength" ) @SuppressWarnings( "checkstyle:methodlength" )
@Override @Override
public ModelBuildingResult build( ModelBuildingRequest request ) public ModelBuildingResult build( ModelBuildingRequest request )
@ -317,7 +332,9 @@ public class DefaultModelBuilder
profileActivationContext, problems ); profileActivationContext, problems );
currentData.setActiveProfiles( activePomProfiles ); currentData.setActiveProfiles( activePomProfiles );
Map<String, Activation> interpolatedActivations = getProfileActivations( rawModel, false ); Map<String, Activation> interpolatedActivations = getInterpolatedActivations( rawModel,
profileActivationContext,
problems );
injectProfileActivations( tmpModel, interpolatedActivations ); injectProfileActivations( tmpModel, interpolatedActivations );
// profile injection // profile injection
@ -440,6 +457,51 @@ public class DefaultModelBuilder
return result; return result;
} }
private Map<String, Activation> getInterpolatedActivations( Model rawModel,
DefaultProfileActivationContext context,
DefaultModelProblemCollector problems )
{
Map<String, Activation> interpolatedActivations = getProfileActivations( rawModel, true );
for ( Activation activation : interpolatedActivations.values() )
{
if ( activation.getFile() != null )
{
replaceWithInterpolatedValue( activation.getFile(), context, problems );
}
}
return interpolatedActivations;
}
private void replaceWithInterpolatedValue( ActivationFile activationFile, ProfileActivationContext context,
DefaultModelProblemCollector problems )
{
try
{
if ( StringUtils.isNotEmpty( activationFile.getExists() ) )
{
String path = activationFile.getExists();
String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context );
activationFile.setExists( absolutePath );
}
else if ( StringUtils.isNotEmpty( activationFile.getMissing() ) )
{
String path = activationFile.getMissing();
String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context );
activationFile.setMissing( absolutePath );
}
}
catch ( InterpolationException e )
{
String path = StringUtils.isNotEmpty(
activationFile.getExists() ) ? activationFile.getExists() : activationFile.getMissing();
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage(
"Failed to interpolate file location " + path + ": " + e.getMessage() ).setLocation(
activationFile.getLocation( StringUtils.isNotEmpty( activationFile.getExists() ) ? "exists" : "missing" ) )
.setException( e ) );
}
}
@Override @Override
public ModelBuildingResult build( ModelBuildingRequest request, ModelBuildingResult result ) public ModelBuildingResult build( ModelBuildingRequest request, ModelBuildingResult result )
throws ModelBuildingException throws ModelBuildingException
@ -818,7 +880,7 @@ public class DefaultModelBuilder
problems.add( mpcr ); problems.add( mpcr );
} }
} }
interpolatedModel.setPomFile( model.getPomFile() ); interpolatedModel.setPomFile( model.getPomFile() );

View File

@ -43,6 +43,7 @@ import org.apache.maven.model.path.DefaultUrlNormalizer;
import org.apache.maven.model.path.ModelPathTranslator; import org.apache.maven.model.path.ModelPathTranslator;
import org.apache.maven.model.path.ModelUrlNormalizer; import org.apache.maven.model.path.ModelUrlNormalizer;
import org.apache.maven.model.path.PathTranslator; import org.apache.maven.model.path.PathTranslator;
import org.apache.maven.model.path.ProfileActivationFilePathInterpolator;
import org.apache.maven.model.path.UrlNormalizer; import org.apache.maven.model.path.UrlNormalizer;
import org.apache.maven.model.plugin.DefaultPluginConfigurationExpander; import org.apache.maven.model.plugin.DefaultPluginConfigurationExpander;
import org.apache.maven.model.plugin.DefaultReportConfigurationExpander; import org.apache.maven.model.plugin.DefaultReportConfigurationExpander;
@ -109,7 +110,13 @@ public class DefaultModelBuilderFactory
protected ProfileActivator[] newProfileActivators() protected ProfileActivator[] newProfileActivators()
{ {
return new ProfileActivator[] { new JdkVersionProfileActivator(), new OperatingSystemProfileActivator(), return new ProfileActivator[] { new JdkVersionProfileActivator(), new OperatingSystemProfileActivator(),
new PropertyProfileActivator(), new FileProfileActivator().setPathTranslator( newPathTranslator() ) }; new PropertyProfileActivator(), new FileProfileActivator()
.setProfileActivationFilePathInterpolator( newProfileActivationFilePathInterpolator() ) };
}
protected ProfileActivationFilePathInterpolator newProfileActivationFilePathInterpolator()
{
return new ProfileActivationFilePathInterpolator().setPathTranslator( newPathTranslator() );
} }
protected UrlNormalizer newUrlNormalizer() protected UrlNormalizer newUrlNormalizer()
@ -225,6 +232,7 @@ public class DefaultModelBuilderFactory
modelBuilder.setPluginConfigurationExpander( newPluginConfigurationExpander() ); modelBuilder.setPluginConfigurationExpander( newPluginConfigurationExpander() );
modelBuilder.setReportConfigurationExpander( newReportConfigurationExpander() ); modelBuilder.setReportConfigurationExpander( newReportConfigurationExpander() );
modelBuilder.setReportingConverter( newReportingConverter() ); modelBuilder.setReportingConverter( newReportingConverter() );
modelBuilder.setProfileActivationFilePathInterpolator( newProfileActivationFilePathInterpolator() );
return modelBuilder; return modelBuilder;
} }

View File

@ -0,0 +1,103 @@
package org.apache.maven.model.path;
/*
* 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.
*/
import org.apache.maven.model.ActivationFile;
import org.apache.maven.model.profile.ProfileActivationContext;
import org.codehaus.plexus.interpolation.AbstractValueSource;
import org.codehaus.plexus.interpolation.InterpolationException;
import org.codehaus.plexus.interpolation.MapBasedValueSource;
import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.File;
/**
* Finds an absolute path for {@link ActivationFile#getExists()} or {@link ActivationFile#getMissing()}
*
* @author Ravil Galeyev
*/
@Named
@Singleton
public class ProfileActivationFilePathInterpolator
{
@Inject
private PathTranslator pathTranslator;
public ProfileActivationFilePathInterpolator setPathTranslator( PathTranslator pathTranslator )
{
this.pathTranslator = pathTranslator;
return this;
}
/**
* Interpolates given {@code path}.
*
* @return absolute path or {@code null} if the input was {@code null}
*/
public String interpolate( String path, ProfileActivationContext context ) throws InterpolationException
{
if ( path == null )
{
return null;
}
RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
final File basedir = context.getProjectDirectory();
if ( basedir != null )
{
interpolator.addValueSource( new AbstractValueSource( false )
{
@Override
public Object getValue( String expression )
{
/*
* We intentionally only support ${basedir} and not ${project.basedir} as the latter form
* would suggest that other project.* expressions can be used which is beyond the design.
*/
if ( "basedir".equals( expression ) )
{
return basedir.getAbsolutePath();
}
return null;
}
} );
}
else if ( path.contains( "${basedir}" ) )
{
return null;
}
interpolator.addValueSource( new MapBasedValueSource( context.getProjectProperties() ) );
interpolator.addValueSource( new MapBasedValueSource( context.getUserProperties() ) );
interpolator.addValueSource( new MapBasedValueSource( context.getSystemProperties() ) );
String absolutePath = interpolator.interpolate( path, "" );
return pathTranslator.alignToBaseDirectory( absolutePath, basedir );
}
}

View File

@ -28,15 +28,13 @@ import javax.inject.Singleton;
import org.apache.maven.model.Activation; import org.apache.maven.model.Activation;
import org.apache.maven.model.ActivationFile; import org.apache.maven.model.ActivationFile;
import org.apache.maven.model.Profile; import org.apache.maven.model.Profile;
import org.apache.maven.model.building.ModelProblemCollector;
import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Severity;
import org.apache.maven.model.building.ModelProblem.Version; import org.apache.maven.model.building.ModelProblem.Version;
import org.apache.maven.model.building.ModelProblemCollector;
import org.apache.maven.model.building.ModelProblemCollectorRequest; import org.apache.maven.model.building.ModelProblemCollectorRequest;
import org.apache.maven.model.path.PathTranslator; import org.apache.maven.model.path.ProfileActivationFilePathInterpolator;
import org.apache.maven.model.profile.ProfileActivationContext; import org.apache.maven.model.profile.ProfileActivationContext;
import org.codehaus.plexus.interpolation.AbstractValueSource; import org.codehaus.plexus.interpolation.InterpolationException;
import org.codehaus.plexus.interpolation.MapBasedValueSource;
import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.StringUtils;
/** /**
@ -58,11 +56,12 @@ public class FileProfileActivator
{ {
@Inject @Inject
private PathTranslator pathTranslator; private ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
public FileProfileActivator setPathTranslator( PathTranslator pathTranslator ) public FileProfileActivator setProfileActivationFilePathInterpolator(
ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator )
{ {
this.pathTranslator = pathTranslator; this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator;
return this; return this;
} }
@ -101,64 +100,23 @@ public class FileProfileActivator
return false; return false;
} }
RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
final File basedir = context.getProjectDirectory();
if ( basedir != null )
{
interpolator.addValueSource( new AbstractValueSource( false )
{
@Override
public Object getValue( String expression )
{
/*
* NOTE: We intentionally only support ${basedir} and not ${project.basedir} as the latter form
* would suggest that other project.* expressions can be used which is however beyond the design.
*/
if ( "basedir".equals( expression ) )
{
return basedir.getAbsolutePath();
}
return null;
}
} );
}
else if ( path.contains( "${basedir}" ) )
{
return false;
}
interpolator.addValueSource( new MapBasedValueSource( context.getProjectProperties() ) );
interpolator.addValueSource( new MapBasedValueSource( context.getUserProperties() ) );
interpolator.addValueSource( new MapBasedValueSource( context.getSystemProperties() ) );
try try
{ {
path = interpolator.interpolate( path, "" ); path = profileActivationFilePathInterpolator.interpolate( path, context );
} }
catch ( Exception e ) catch ( InterpolationException e )
{ {
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ) problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
.setMessage( "Failed to interpolate file location " + path + " for profile " + profile.getId() .setMessage( "Failed to interpolate file location " + path + " for profile " + profile.getId()
+ ": " + e.getMessage() ) + ": " + e.getMessage() )
.setLocation( file.getLocation( missing ? "missing" : "exists" ) ) .setLocation( file.getLocation( missing ? "missing" : "exists" ) )
.setException( e ) ); .setException( e ) );
return false; return false;
} }
path = pathTranslator.alignToBaseDirectory( path, basedir ); if ( path == null )
// replace activation value with interpolated value
if ( missing )
{ {
file.setMissing( path ); return false;
}
else
{
file.setExists( path );
} }
File f = new File( path ); File f = new File( path );

View File

@ -20,11 +20,17 @@ package org.apache.maven.model.building;
*/ */
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.nio.file.Paths;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3Dom;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.junit.Test;
/** /**
* @author Benjamin Bentmann * @author Benjamin Bentmann
*/ */
@ -32,9 +38,11 @@ public class DefaultModelBuilderFactoryTest
extends TestCase extends TestCase
{ {
private static final String BASE_DIR = Paths.get( "src", "test", "resources", "poms", "factory" ).toString();
private File getPom( String name ) private File getPom( String name )
{ {
return new File( "src/test/resources/poms/factory/" + name + ".xml" ).getAbsoluteFile(); return new File( Paths.get( BASE_DIR, name + ".xml" ).toString() ).getAbsoluteFile();
} }
public void testCompleteWiring() public void testCompleteWiring()
@ -56,4 +64,30 @@ public class DefaultModelBuilderFactoryTest
assertEquals( " 1.5 ", conf.getChild( "target" ).getValue() ); assertEquals( " 1.5 ", conf.getChild( "target" ).getValue() );
} }
@Test
public void testPomChanges() throws Exception
{
ModelBuilder builder = new DefaultModelBuilderFactory().newInstance();
assertNotNull( builder );
File pom = getPom( "simple" );
String originalExists = readPom( pom ).getProfiles().get( 1 ).getActivation().getFile().getExists();
DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
request.setProcessPlugins( true );
request.setPomFile( pom );
ModelBuildingResult result = builder.build( request );
String resultExists = result.getRawModel().getProfiles().get( 1 ).getActivation().getFile().getExists();
assertEquals( originalExists, resultExists );
assertTrue( result.getEffectiveModel().getProfiles().get( 1 ).getActivation().getFile().getExists()
.contains( BASE_DIR ) );
}
private static Model readPom( File file ) throws Exception
{
MavenXpp3Reader reader = new MavenXpp3Reader();
return reader.read( new FileInputStream( file ) );
}
} }

View File

@ -0,0 +1,131 @@
package org.apache.maven.model.profile.activation;
/*
* 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.
*/
import org.apache.maven.model.Activation;
import org.apache.maven.model.ActivationFile;
import org.apache.maven.model.Profile;
import org.apache.maven.model.path.DefaultPathTranslator;
import org.apache.maven.model.path.ProfileActivationFilePathInterpolator;
import org.apache.maven.model.profile.DefaultProfileActivationContext;
import org.junit.Before;
import org.junit.Test;
import java.nio.file.Files;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
/**
* Tests {@link FileProfileActivator}.
*
* @author Ravil Galeyev
*/
public class FileProfileActivatorTest extends AbstractProfileActivatorTest<FileProfileActivator>
{
Path tempDir;
private final DefaultProfileActivationContext context = new DefaultProfileActivationContext();
public FileProfileActivatorTest()
{
super( FileProfileActivator.class );
}
@Before
public void setUp() throws Exception
{
super.setUp();
tempDir = Files.createTempDirectory( null );
activator.setProfileActivationFilePathInterpolator(
new ProfileActivationFilePathInterpolator().setPathTranslator( new DefaultPathTranslator() ) );
context.setProjectDirectory( new File( tempDir.toString() ) );
File file = new File( tempDir.resolve( "file.txt" ).toString() );
if ( !file.createNewFile() )
{
throw new IOException( "Can't create " + file );
}
}
@Test
public void testIsActiveNoFile()
{
assertActivation( false, newExistsProfile( null ), context );
assertActivation( false, newExistsProfile( "someFile.txt" ), context );
assertActivation( false, newExistsProfile( "${basedir}/someFile.txt" ), context );
assertActivation( false, newMissingProfile( null ), context );
assertActivation( true, newMissingProfile( "someFile.txt" ), context );
assertActivation( true, newMissingProfile( "${basedir}/someFile.txt" ), context );
}
@Test
public void testIsActiveExistsFileExists()
{
assertActivation( true, newExistsProfile( "file.txt" ), context );
assertActivation( true, newExistsProfile( "${basedir}" ), context );
assertActivation( true, newExistsProfile( "${basedir}/" + "file.txt" ), context );
assertActivation( false, newMissingProfile( "file.txt" ), context );
assertActivation( false, newMissingProfile( "${basedir}" ), context );
assertActivation( false, newMissingProfile( "${basedir}/" + "file.txt" ), context );
}
@Test
public void testIsActiveExistsLeavesFileUnchanged()
{
Profile profile = newExistsProfile( "file.txt" );
assertEquals( "file.txt", profile.getActivation().getFile().getExists() );
assertActivation( true, profile, context );
assertEquals( "file.txt", profile.getActivation().getFile().getExists() );
}
private Profile newExistsProfile( String filePath )
{
ActivationFile activationFile = new ActivationFile();
activationFile.setExists( filePath );
return newProfile( activationFile );
}
private Profile newMissingProfile( String filePath )
{
ActivationFile activationFile = new ActivationFile();
activationFile.setMissing( filePath );
return newProfile( activationFile );
}
private Profile newProfile( ActivationFile activationFile )
{
Activation activation = new Activation();
activation.setFile( activationFile );
Profile profile = new Profile();
profile.setActivation( activation );
return profile;
}
}