[MNG-7051] Optionally skip non-existing profiles and break on missing required profiles.

This commit is contained in:
Maarten Mulders 2020-12-09 14:43:15 +01:00 committed by Martin Kanters
parent 8df10f93be
commit 8defd16965
11 changed files with 496 additions and 112 deletions

View File

@ -19,22 +19,6 @@
* under the License.
*/
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.execution.BuildResumptionAnalyzer;
import org.apache.maven.execution.BuildResumptionDataRepository;
@ -44,15 +28,19 @@
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ProfileActivation;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.graph.GraphBuilder;
import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
import org.apache.maven.lifecycle.internal.LifecycleStarter;
import org.apache.maven.model.Model;
import org.apache.maven.model.Prerequisites;
import org.apache.maven.model.Profile;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.building.Result;
import org.apache.maven.model.superpom.SuperPomProvider;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
@ -66,6 +54,26 @@
import org.eclipse.aether.repository.WorkspaceReader;
import org.eclipse.aether.util.repository.ChainedWorkspaceReader;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toSet;
/**
* @author Jason van Zyl
*/
@ -109,6 +117,9 @@ public class DefaultMaven
@Inject
private BuildResumptionDataRepository buildResumptionDataRepository;
@Inject
private SuperPomProvider superPomProvider;
@Override
public MavenExecutionResult execute( MavenExecutionRequest request )
{
@ -316,11 +327,17 @@ private MavenExecutionResult doExecute( MavenExecutionRequest request, MavenSess
validatePrerequisitesForNonMavenPluginProjects( session.getProjects() );
validateActivatedProfiles( session.getProjects(), request.getActiveProfiles() );
validateRequiredProfiles( session, request.getProfileActivation() );
if ( session.getResult().hasExceptions() )
{
return result;
}
validateOptionalProfiles( session, request.getProfileActivation() );
lifecycleStarter.execute( session );
validateActivatedProfiles( session.getProjects(), request.getActiveProfiles() );
validateOptionalProfiles( session, request.getProfileActivation() );
if ( session.getResult().hasExceptions() )
{
@ -493,22 +510,93 @@ private void validatePrerequisitesForNonMavenPluginProjects( List<MavenProject>
}
}
private void validateActivatedProfiles( List<MavenProject> projects, List<String> activeProfileIds )
/**
* Get all profiles that are detected in the projects, any parent of the projects, or the settings.
* @param session The Maven session
* @return A {@link Set} of profile identifiers, never {@code null}.
*/
private Set<String> getAllProfiles( MavenSession session )
{
Collection<String> notActivatedProfileIds = new LinkedHashSet<>( activeProfileIds );
for ( MavenProject project : projects )
final Model superPomModel = superPomProvider.getSuperModel( "4.0.0" );
final Set<MavenProject> projectsIncludingParents = new HashSet<>();
for ( MavenProject project : session.getProjects() )
{
for ( List<String> profileIds : project.getInjectedProfileIds().values() )
boolean isAdded = projectsIncludingParents.add( project );
MavenProject parent = project.getParent();
while ( isAdded && parent != null )
{
notActivatedProfileIds.removeAll( profileIds );
isAdded = projectsIncludingParents.add( parent );
parent = parent.getParent();
}
}
for ( String notActivatedProfileId : notActivatedProfileIds )
final Stream<String> projectProfiles = projectsIncludingParents.stream()
.map( MavenProject::getModel )
.map( Model::getProfiles )
.flatMap( Collection::stream )
.map( Profile::getId );
final Stream<String> settingsProfiles = session.getSettings().getProfiles().stream()
.map( org.apache.maven.settings.Profile::getId );
final Stream<String> superPomProfiles = superPomModel.getProfiles().stream()
.map( Profile::getId );
return Stream.of( projectProfiles, settingsProfiles, superPomProfiles )
.flatMap( Function.identity() )
.collect( toSet() );
}
/**
* Check whether the required profiles were found in any of the projects we're building or the settings.
* @param session the Maven session.
* @param profileActivation the requested optional and required profiles.
*/
private void validateRequiredProfiles( MavenSession session, ProfileActivation profileActivation )
{
final Set<String> allAvailableProfiles = getAllProfiles( session );
final Set<String> requiredProfiles = new HashSet<>( );
requiredProfiles.addAll( profileActivation.getRequiredActiveProfileIds() );
requiredProfiles.addAll( profileActivation.getRequiredInactiveProfileIds() );
// Check whether the required profiles were found in any of the projects we're building.
final Set<String> notFoundRequiredProfiles = requiredProfiles.stream()
.filter( rap -> !allAvailableProfiles.contains( rap ) )
.collect( toSet() );
if ( !notFoundRequiredProfiles.isEmpty() )
{
logger.warn( "The requested profile \"" + notActivatedProfileId
+ "\" could not be activated because it does not exist." );
final String message = String.format(
"The requested profiles [%s] could not be activated or deactivated because they do not exist.",
String.join( ", ", notFoundRequiredProfiles )
);
addExceptionToResult( session.getResult(), new MissingProfilesException( message ) );
}
}
/**
* Check whether any of the requested optional profiles were not activated or deactivated.
* @param session the Maven session.
* @param profileActivation the requested optional and required profiles.
*/
private void validateOptionalProfiles( MavenSession session, ProfileActivation profileActivation )
{
final Set<String> allAvailableProfiles = getAllProfiles( session );
final Set<String> optionalProfiles = new HashSet<>( );
optionalProfiles.addAll( profileActivation.getOptionalActiveProfileIds() );
optionalProfiles.addAll( profileActivation.getOptionalInactiveProfileIds() );
final Set<String> notFoundOptionalProfiles = optionalProfiles.stream()
.filter( rap -> !allAvailableProfiles.contains( rap ) )
.collect( toSet() );
if ( !notFoundOptionalProfiles.isEmpty() )
{
final String message = String.format(
"The requested optional profiles [%s] could not be activated or deactivated because they "
+ "do not exist.", String.join( ", ", notFoundOptionalProfiles )
);
logger.warn( message );
}
}

View File

@ -0,0 +1,33 @@
package org.apache.maven;
/*
* 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.
*/
/**
* Signals that the user referenced one or more Maven profiles that could not be located in either the project or the
* settings.
*/
public class MissingProfilesException
extends Exception
{
public MissingProfilesException( String message )
{
super( message );
}
}

View File

@ -76,6 +76,8 @@ public class DefaultMavenExecutionRequest
private List<Profile> profiles;
private final ProfileActivation profileActivation = new ProfileActivation();
private List<String> pluginGroups;
private boolean isProjectPresent = true;
@ -130,10 +132,6 @@ public class DefaultMavenExecutionRequest
private boolean showErrors = false;
private List<String> activeProfiles;
private List<String> inactiveProfiles;
private TransferListener transferListener;
private int loggingLevel = LOGGING_LEVEL_INFO;
@ -343,11 +341,7 @@ public MavenExecutionRequest setActiveProfiles( List<String> activeProfiles )
{
if ( activeProfiles != null )
{
this.activeProfiles = new ArrayList<>( activeProfiles );
}
else
{
this.activeProfiles = null;
this.profileActivation.overwriteActiveProfiles( activeProfiles );
}
return this;
@ -358,16 +352,18 @@ public MavenExecutionRequest setInactiveProfiles( List<String> inactiveProfiles
{
if ( inactiveProfiles != null )
{
this.inactiveProfiles = new ArrayList<>( inactiveProfiles );
}
else
{
this.inactiveProfiles = null;
this.profileActivation.overwriteInactiveProfiles( inactiveProfiles );
}
return this;
}
@Override
public ProfileActivation getProfileActivation()
{
return this.profileActivation;
}
@Override
public MavenExecutionRequest setRemoteRepositories( List<ArtifactRepository> remoteRepositories )
{
@ -406,21 +402,13 @@ public void setProjectBuildingConfiguration( ProjectBuildingRequest projectBuild
@Override
public List<String> getActiveProfiles()
{
if ( activeProfiles == null )
{
activeProfiles = new ArrayList<>();
}
return activeProfiles;
return this.profileActivation.getActiveProfiles();
}
@Override
public List<String> getInactiveProfiles()
{
if ( inactiveProfiles == null )
{
inactiveProfiles = new ArrayList<>();
}
return inactiveProfiles;
return this.profileActivation.getInactiveProfiles();
}
@Override

View File

@ -277,22 +277,62 @@ public interface MavenExecutionRequest
MavenExecutionRequest setProfiles( List<Profile> profiles );
/**
* @deprecated Use {@link #getProfileActivation()}.
*/
@Deprecated
MavenExecutionRequest addActiveProfile( String profile );
/**
* @deprecated Use {@link #getProfileActivation()}.
*/
@Deprecated
MavenExecutionRequest addActiveProfiles( List<String> profiles );
/**
* @deprecated Use {@link #getProfileActivation()}.
*/
@Deprecated
MavenExecutionRequest setActiveProfiles( List<String> profiles );
/**
* @return The list of profiles that the user wants to activate.
* @deprecated Use {@link #getProfileActivation()}.
*/
@Deprecated
List<String> getActiveProfiles();
/**
* @deprecated Use {@link #getProfileActivation()}.
*/
@Deprecated
MavenExecutionRequest addInactiveProfile( String profile );
/**
* @deprecated Use {@link #getProfileActivation()}.
*/
@Deprecated
MavenExecutionRequest addInactiveProfiles( List<String> profiles );
/**
* @deprecated Use {@link #getProfileActivation()}.
*/
@Deprecated
MavenExecutionRequest setInactiveProfiles( List<String> profiles );
/**
* @return The list of profiles that the user wants to de-activate.
* @deprecated Use {@link #getProfileActivation()}.
*/
@Deprecated
List<String> getInactiveProfiles();
/**
* Return the requested activation(s) of profile(s) in this execution.
* @return requested (de-)activation(s) of profile(s) in this execution. Never {@code null}.
*/
ProfileActivation getProfileActivation();
// Proxies
List<Proxy> getProxies();

View File

@ -0,0 +1,201 @@
package org.apache.maven.execution;
/*
* 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 java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import static java.util.stream.Collectors.toSet;
/**
* Container for storing the request from the user to activate or de-activate certain profiles and optionally fail the
* build if those profiles do not exist.
*/
public class ProfileActivation
{
private enum ActivationSettings
{
ACTIVATION_OPTIONAL( true, true ),
ACTIVATION_REQUIRED( true, false ),
DEACTIVATION_OPTIONAL( false, true ),
DEACTIVATION_REQUIRED( false, false );
/** Should the profile be active? */
final boolean active;
/** Should the build continue if the profile is not present? */
final boolean optional;
ActivationSettings( final boolean active, final boolean optional )
{
this.active = active;
this.optional = optional;
}
static ActivationSettings of( final boolean active, final boolean optional )
{
if ( optional )
{
return active ? ACTIVATION_OPTIONAL : DEACTIVATION_OPTIONAL;
}
else
{
return active ? ACTIVATION_REQUIRED : DEACTIVATION_REQUIRED;
}
}
}
private final Map<String, ActivationSettings> activations = new HashMap<>();
/**
* Mimics the pre-Maven 4 "active profiles" list.
* @deprecated Use {@link #getRequiredActiveProfileIds()} and {@link #getOptionalActiveProfileIds()} instead.
*/
@Deprecated
public List<String> getActiveProfiles()
{
return new ArrayList<>( getProfileIds( pa -> pa.active ) );
}
/**
* Mimics the pre-Maven 4 "inactive profiles" list.
* @deprecated Use {@link #getRequiredInactiveProfileIds()} and {@link #getOptionalInactiveProfileIds()} instead.
*/
@Deprecated
public List<String> getInactiveProfiles()
{
return new ArrayList<>( getProfileIds( pa -> !pa.active ) );
}
/**
* Overwrites the active profiles based on a pre-Maven 4 "active profiles" list.
* @param activeProfileIds A {@link List} of profile IDs that must be activated.
* @deprecated Use {@link #activateOptionalProfile(String)} or {@link #activateRequiredProfile(String)} instead.
*/
@Deprecated
public void overwriteActiveProfiles( List<String> activeProfileIds )
{
getActiveProfiles().forEach( this.activations::remove );
activeProfileIds.forEach( this::activateOptionalProfile );
}
/**
* Overwrites the inactive profiles based on a pre-Maven 4 "inactive profiles" list.
* @param inactiveProfileIds A {@link List} of profile IDs that must be deactivated.
* @deprecated Use {@link #deactivateOptionalProfile(String)} or {@link #deactivateRequiredProfile(String)} instead.
*/
@Deprecated
public void overwriteInactiveProfiles( List<String> inactiveProfileIds )
{
getInactiveProfiles().forEach( this.activations::remove );
inactiveProfileIds.forEach( this::deactivateOptionalProfile );
}
/**
* Mark a profile as required and activated.
* @param id The identifier of the profile.
*/
public void activateRequiredProfile( String id )
{
this.activations.put( id, ActivationSettings.ACTIVATION_REQUIRED );
}
/**
* Mark a profile as optional and activated.
* @param id The identifier of the profile.
*/
public void activateOptionalProfile( String id )
{
this.activations.put( id, ActivationSettings.ACTIVATION_OPTIONAL );
}
/**
* Mark a profile as required and deactivated.
* @param id The identifier of the profile.
*/
public void deactivateRequiredProfile( String id )
{
this.activations.put( id, ActivationSettings.DEACTIVATION_REQUIRED );
}
/**
* Mark a profile as optional and deactivated.
* @param id The identifier of the profile.
*/
public void deactivateOptionalProfile( String id )
{
this.activations.put( id, ActivationSettings.DEACTIVATION_OPTIONAL );
}
/**
* Adds a profile activation to the request.
* @param id The identifier of the profile.
* @param active Should the profile be activated?
* @param optional Can the build continue if the profile does not exist?
*/
public void addProfileActivation( String id, boolean active, boolean optional )
{
final ActivationSettings settings = ActivationSettings.of( active, optional );
this.activations.put( id, settings );
}
private Set<String> getProfileIds( final Predicate<ActivationSettings> predicate )
{
return this.activations.entrySet().stream()
.filter( e -> predicate.test( e.getValue() ) )
.map( e -> e.getKey() )
.collect( toSet() );
}
/**
* @return Required active profile identifiers, never {@code null}.
*/
public Set<String> getRequiredActiveProfileIds()
{
return getProfileIds( pa -> !pa.optional && pa.active );
}
/**
* @return Optional active profile identifiers, never {@code null}.
*/
public Set<String> getOptionalActiveProfileIds()
{
return getProfileIds( pa -> pa.optional && pa.active );
}
/**
* @return Required inactive profile identifiers, never {@code null}.
*/
public Set<String> getRequiredInactiveProfileIds()
{
return getProfileIds( pa -> !pa.optional && !pa.active );
}
/**
* @return Optional inactive profile identifiers, never {@code null}.
*/
public Set<String> getOptionalInactiveProfileIds()
{
return getProfileIds( pa -> pa.optional && !pa.active );
}
}

View File

@ -54,6 +54,7 @@
import org.apache.maven.execution.MavenExecutionRequestPopulationException;
import org.apache.maven.execution.MavenExecutionRequestPopulator;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.ProfileActivation;
import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule;
import org.apache.maven.extension.internal.CoreExports;
import org.apache.maven.extension.internal.CoreExtensionEntry;
@ -1379,9 +1380,7 @@ private MavenExecutionRequest populateRequest( CliRequest cliRequest, MavenExecu
request.setSelectedProjects( projectActivation.activeProjects );
request.setExcludedProjects( projectActivation.inactiveProjects );
final ProfileActivation profileActivation = determineProfileActivation( commandLine );
request.addActiveProfiles( profileActivation.activeProfiles );
request.addInactiveProfiles( profileActivation.inactiveProfiles );
performProfileActivation( commandLine, request.getProfileActivation() );
final String localRepositoryPath = determineLocalRepositoryPath( request );
if ( localRepositoryPath != null )
@ -1507,41 +1506,41 @@ else if ( projectAction.startsWith( "+" ) )
}
// Visible for testing
static ProfileActivation determineProfileActivation( final CommandLine commandLine )
static void performProfileActivation( final CommandLine commandLine,
final ProfileActivation profileActivation )
{
final ProfileActivation result = new ProfileActivation();
if ( commandLine.hasOption( CLIManager.ACTIVATE_PROFILES ) )
{
String[] profileOptionValues = commandLine.getOptionValues( CLIManager.ACTIVATE_PROFILES );
if ( profileOptionValues != null )
final String[] optionValues = commandLine.getOptionValues( CLIManager.ACTIVATE_PROFILES );
if ( optionValues == null || optionValues.length == 0 )
{
for ( String profileOptionValue : profileOptionValues )
return;
}
for ( final String optionValue : optionValues )
{
for ( String token : optionValue.split( "," ) )
{
StringTokenizer profileTokens = new StringTokenizer( profileOptionValue, "," );
while ( profileTokens.hasMoreTokens() )
String profileId = token.trim();
boolean active = true;
if ( profileId.charAt( 0 ) == '-' || profileId.charAt( 0 ) == '!' )
{
String profileAction = profileTokens.nextToken().trim();
if ( profileAction.startsWith( "-" ) || profileAction.startsWith( "!" ) )
{
result.deactivate( profileAction.substring( 1 ) );
}
else if ( profileAction.startsWith( "+" ) )
{
result.activate( profileAction.substring( 1 ) );
}
else
{
result.activate( profileAction );
}
active = false;
profileId = profileId.substring( 1 );
}
else if ( token.charAt( 0 ) == '+' )
{
profileId = profileId.substring( 1 );
}
boolean optional = profileId.charAt( 0 ) == '?';
profileId = profileId.substring( optional ? 1 : 0 );
profileActivation.addProfileActivation( profileId, active, optional );
}
}
}
return result;
}
private ExecutionListener determineExecutionListener()
@ -1796,23 +1795,6 @@ protected ModelProcessor createModelProcessor( PlexusContainer container )
return container.lookup( ModelProcessor.class );
}
// Visible for testing
static class ProfileActivation
{
final List<String> activeProfiles = new ArrayList<>();
final List<String> inactiveProfiles = new ArrayList<>();
public void deactivate( final String profile )
{
inactiveProfiles.add( profile );
}
public void activate( final String profile )
{
activeProfiles.add( profile );
}
}
// Visible for testing
static class ProjectActivation
{

View File

@ -20,7 +20,7 @@
*/
import static java.util.Arrays.asList;
import static org.apache.maven.cli.MavenCli.determineProfileActivation;
import static org.apache.maven.cli.MavenCli.performProfileActivation;
import static org.apache.maven.cli.MavenCli.determineProjectActivation;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
@ -33,6 +33,7 @@
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@ -46,9 +47,11 @@
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.Parser;
import org.apache.maven.Maven;
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.ProfileActivation;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.utils.logging.MessageUtils;
import org.apache.maven.toolchain.building.ToolchainsBuildingRequest;
@ -88,25 +91,29 @@ public void tearDown()
}
@Test
public void testDetermineProfileActivation() throws ParseException
public void testPerformProfileActivation() throws ParseException
{
MavenCli.ProfileActivation result;
Options options = new Options();
final Parser parser = new GnuParser();
final Options options = new Options();
options.addOption( Option.builder( Character.toString( CLIManager.ACTIVATE_PROFILES ) ).hasArg().build() );
result = determineProfileActivation( new GnuParser().parse( options, new String[]{ "-P", "test1,+test2" } ) );
assertThat( result.activeProfiles.size(), is( 2 ) );
assertThat( result.activeProfiles, contains( "test1", "test2" ) );
ProfileActivation activation;
result = determineProfileActivation( new GnuParser().parse( options, new String[]{ "-P", "!test1,-test2" } ) );
assertThat( result.inactiveProfiles.size(), is( 2 ) );
assertThat( result.inactiveProfiles, contains( "test1", "test2" ) );
activation = new ProfileActivation();
performProfileActivation( parser.parse( options, new String[]{ "-P", "test1,+test2,?test3,+?test4" } ), activation );
assertThat( activation.getRequiredActiveProfileIds(), containsInAnyOrder( "test1", "test2" ) );
assertThat( activation.getOptionalActiveProfileIds(), containsInAnyOrder( "test3", "test4" ) );
result = determineProfileActivation( new GnuParser().parse( options, new String[]{ "-P", "-test1,+test2" } ) );
assertThat( result.activeProfiles.size(), is( 1 ) );
assertThat( result.activeProfiles, contains( "test2" ) );
assertThat( result.inactiveProfiles.size(), is( 1 ) );
assertThat( result.inactiveProfiles, contains( "test1" ) );
activation = new ProfileActivation();
performProfileActivation( parser.parse( options, new String[]{ "-P", "!test1,-test2,-?test3,!?test4" } ), activation );
assertThat( activation.getRequiredInactiveProfileIds(), containsInAnyOrder( "test1", "test2" ) );
assertThat( activation.getOptionalInactiveProfileIds(), containsInAnyOrder( "test3", "test4" ) );
activation = new ProfileActivation();
performProfileActivation( parser.parse( options, new String[]{ "-P", "-test1,+test2" } ), activation );
assertThat( activation.getRequiredActiveProfileIds(), containsInAnyOrder( "test2" ) );
assertThat( activation.getRequiredInactiveProfileIds(), containsInAnyOrder( "test1" ) );
}
@Test

View File

@ -51,7 +51,8 @@ enum Version
V20,
V30,
V31,
V37
V37,
V40
}
/**

View File

@ -190,6 +190,8 @@ public void validateFileModel( Model m, ModelBuildingRequest request, ModelProbl
{
String prefix = "profiles.profile[" + profile.getId() + "].";
validateId( prefix, "id", problems, Severity.ERROR, Version.V40, profile.getId(), null, m );
if ( !profileIds.add( profile.getId() ) )
{
addViolation( problems, errOn30, Version.V20, "profiles.profile.id", null,

View File

@ -403,6 +403,16 @@ public void testDuplicateModule()
}
@Test
public void testInvalidProfileId()
throws Exception
{
SimpleProblemCollector result = validateRaw( "invalid-profile-id.xml" );
assertViolations( result, 0, 1, 0 );
assertTrue( result.getErrors().get( 0 ).contains( "?invalid-id" ) );
}
public void testDuplicateProfileId()
throws Exception
{

View File

@ -0,0 +1,32 @@
<!--
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>
<modelVersion>4.0.0</modelVersion>
<artifactId>aid</artifactId>
<groupId>gid</groupId>
<version>0.1</version>
<packaging>pom</packaging>
<profiles>
<profile>
<id>?invalid-id</id>
</profile>
</profiles>
</project>