diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java index 544ec37b14..c24b1ad7d4 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultMavenProjectBuilder.java @@ -43,11 +43,9 @@ import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.apache.maven.model.lifecycle.LifecycleBindingsInjector; import org.apache.maven.model.normalization.Normalizer; import org.apache.maven.model.plugin.PluginConfigurationExpander; -import org.apache.maven.profiles.DefaultProfileManager; -import org.apache.maven.profiles.ProfileActivationContext; -import org.apache.maven.profiles.ProfileActivationException; +import org.apache.maven.model.profile.ProfileActivationException; +import org.apache.maven.model.profile.ProfileSelector; import org.apache.maven.profiles.ProfileManager; -import org.apache.maven.profiles.ProfileManagerInfo; import org.apache.maven.project.validation.ModelValidationResult; import org.apache.maven.project.validation.ModelValidator; import org.apache.maven.repository.RepositorySystem; @@ -86,6 +84,9 @@ public class DefaultMavenProjectBuilder @Requirement private Interpolator interpolator; + @Requirement + private ProfileSelector profileSelector; + @Requirement private LifecycleBindingsInjector lifecycleBindingsInjector; @@ -117,16 +118,10 @@ public class DefaultMavenProjectBuilder } DomainModel domainModel; - - ProfileActivationContext profileActivationContext = new ProfileActivationContext( configuration.getExecutionProperties(), true ); - profileActivationContext.setExplicitlyActiveProfileIds( configuration.getActiveProfileIds() ); - profileActivationContext.setExplicitlyInactiveProfileIds( configuration.getInactiveProfileIds() ); - - ProfileManager profileManager = new DefaultProfileManager( profileActivationContext ); try { - domainModel = build( "unknown", pomFile, profileManager, configuration ); + domainModel = build( "unknown", pomFile, configuration ); } catch ( IOException e ) { @@ -141,13 +136,13 @@ public class DefaultMavenProjectBuilder try { - projectProfiles = new ArrayList(); - profileManager.addProfiles( domainModel.getModel().getProfiles() ); + projectProfiles = new ArrayList(); + projectProfiles.addAll( domainModel.getModel().getProfiles() ); if ( configuration.getProfiles() != null ) { - profileManager.addProfiles( configuration.getProfiles() ); + projectProfiles.addAll( configuration.getProfiles() ); } - projectProfiles.addAll( profileManager.getActiveProfiles() ); + projectProfiles = profileSelector.getActiveProfiles( projectProfiles, configuration ); } catch ( ProfileActivationException e ) { @@ -382,16 +377,9 @@ public class DefaultMavenProjectBuilder return project; } - private DomainModel build( String projectId, File pomFile, ProfileManager profileManager, ProjectBuilderConfiguration projectBuilderConfiguration ) + private DomainModel build( String projectId, File pomFile, ProjectBuilderConfiguration projectBuilderConfiguration ) throws ProjectBuildingException, IOException { - List activeProfileIds = ( projectBuilderConfiguration != null && profileManager != null && profileManager.getProfileActivationContext() != null ) ? profileManager - .getProfileActivationContext().getExplicitlyActiveProfileIds() : new ArrayList(); - - List inactiveProfileIds = ( projectBuilderConfiguration != null && profileManager != null && profileManager.getProfileActivationContext() != null ) ? profileManager - .getProfileActivationContext().getExplicitlyInactiveProfileIds() : new ArrayList(); - - ProfileManagerInfo profileInfo = new ProfileManagerInfo( projectBuilderConfiguration.getExecutionProperties(), activeProfileIds, inactiveProfileIds ); DomainModel domainModel = new DomainModel( pomFile ); domainModel.setProjectDirectory( pomFile.getParentFile() ); domainModel.setMostSpecialized( true ); @@ -442,7 +430,16 @@ public class DefaultMavenProjectBuilder if ( !dm.getModel().getProfiles().isEmpty() ) { - Collection profiles = DefaultProfileManager.getActiveProfiles( dm.getModel().getProfiles(), profileInfo ); + Collection profiles; + try + { + profiles = + profileSelector.getActiveProfiles( dm.getModel().getProfiles(), projectBuilderConfiguration ); + } + catch ( ProfileActivationException e ) + { + throw new ProjectBuildingException( projectId, "Failed to determine active profiles", pomFile, e ); + } if ( !profiles.isEmpty() ) { for ( Profile p : profiles ) diff --git a/maven-core/src/main/java/org/apache/maven/project/ProjectBuilderConfiguration.java b/maven-core/src/main/java/org/apache/maven/project/ProjectBuilderConfiguration.java index e00f2daaf8..b38932206e 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ProjectBuilderConfiguration.java +++ b/maven-core/src/main/java/org/apache/maven/project/ProjectBuilderConfiguration.java @@ -5,8 +5,10 @@ import java.util.Properties; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.model.Profile; +import org.apache.maven.model.profile.ProfileActivationContext; public interface ProjectBuilderConfiguration + extends ProfileActivationContext { ProjectBuilderConfiguration setLocalRepository( ArtifactRepository localRepository ); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java new file mode 100644 index 0000000000..f93d5ce727 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java @@ -0,0 +1,111 @@ +package org.apache.maven.model.profile; + +/* + * 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.Collection; +import java.util.HashSet; +import java.util.List; + +import org.apache.maven.model.Activation; +import org.apache.maven.model.Profile; +import org.apache.maven.model.profile.activator.ProfileActivator; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; + +/** + * Calculates the active profiles among a given collection of profiles. + * + * @author Benjamin Bentmann + */ +@Component( role = ProfileSelector.class ) +public class DefaultProfileSelector + implements ProfileSelector +{ + + @Requirement( role = ProfileActivator.class ) + private List activators; + + public List getActiveProfiles( Collection profiles, ProfileActivationContext context ) + throws ProfileActivationException + { + Collection activatedIds = new HashSet( context.getActiveProfileIds() ); + Collection deactivatedIds = new HashSet( context.getInactiveProfileIds() ); + + List activeProfiles = new ArrayList( profiles.size() ); + List activePomProfilesByDefault = new ArrayList(); + boolean activatedPomProfileNotByDefault = false; + + for ( Profile profile : profiles ) + { + if ( !deactivatedIds.contains( profile.getId() ) ) + { + if ( activatedIds.contains( profile.getId() ) || isActive( profile, context ) ) + { + activeProfiles.add( profile ); + + if ( Profile.SOURCE_POM.equals( profile.getSource() ) ) + { + activatedPomProfileNotByDefault = true; + } + } + else if ( isActiveByDefault( profile ) ) + { + if ( Profile.SOURCE_POM.equals( profile.getSource() ) ) + { + activePomProfilesByDefault.add( profile ); + } + else + { + activeProfiles.add( profile ); + } + } + + } + } + + if ( !activatedPomProfileNotByDefault ) + { + activeProfiles.addAll( activePomProfilesByDefault ); + } + + return activeProfiles; + } + + private boolean isActive( Profile profile, ProfileActivationContext context ) + throws ProfileActivationException + { + for ( ProfileActivator activator : activators ) + { + if ( activator.isActive( profile, context ) ) + { + return true; + } + } + return false; + } + + private boolean isActiveByDefault( Profile profile ) + { + Activation activation = profile.getActivation(); + return activation != null && activation.isActiveByDefault(); + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileActivationContext.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileActivationContext.java new file mode 100644 index 0000000000..925f523519 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileActivationContext.java @@ -0,0 +1,54 @@ +package org.apache.maven.model.profile; + +/* + * 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.List; +import java.util.Properties; + +/** + * Describes the environmental context used to determine the activation status of profiles. + * + * @author Benjamin Bentmann + */ +public interface ProfileActivationContext +{ + + /** + * Gets the identifiers of those profiles that should be activated by explicit demand. + * + * @return The identifiers of those profiles to activate, never {@code null}. + */ + List getActiveProfileIds(); + + /** + * Gets the identifiers of those profiles that should be deactivated by explicit demand. + * + * @return The identifiers of those profiles to deactivate, never {@code null}. + */ + List getInactiveProfileIds(); + + /** + * Gets the execution properties. + * + * @return The execution properties, never {@code null}. + */ + Properties getExecutionProperties(); + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileActivationException.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileActivationException.java new file mode 100644 index 0000000000..3972fc5e4b --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileActivationException.java @@ -0,0 +1,72 @@ +package org.apache.maven.model.profile; + +/* + * 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.Profile; + +/** + * Signals an error in determining the activation status of a profile (e.g. bad syntax of activation condition). + * + * @author Benjamin Bentmann + */ +public class ProfileActivationException + extends Exception +{ + + /** + * The profile which raised this error, can be {@code null}. + */ + private Profile profile; + + /** + * Creates a new exception with specified detail message and cause for the given profile. + * + * @param profile The profile that caused the error, may be {@code null}. + * @param message The detail message, may be {@code null}. + * @param cause The cause, may be {@code null}. + */ + public ProfileActivationException( Profile profile, String message, Throwable cause ) + { + super( message, cause ); + this.profile = profile; + } + + /** + * Creates a new exception with specified detail message for the given profile. + * + * @param profile The profile that caused the error, may be {@code null}. + * @param message The detail message, may be {@code null}. + */ + public ProfileActivationException( Profile profile, String message ) + { + super( message ); + } + + /** + * Gets the profile that causes this error (if any). + * + * @return The profile that causes this error or {@code null} if not applicable. + */ + public Profile getProfile() + { + return profile; + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java new file mode 100644 index 0000000000..5afda026e6 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java @@ -0,0 +1,49 @@ +package org.apache.maven.model.profile; + +/* + * 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.Collection; +import java.util.List; + +import org.apache.maven.model.Profile; + +/** + * Calculates the active profiles among a given collection of profiles. + * + * @author Benjamin Bentmann + */ +public interface ProfileSelector +{ + + /** + * Determines the profiles which are active in the specified activation context. Active profiles will eventually be + * injected into the model. + * + * @param profiles The profiles whose activation status should be determined, must not be {@code null}. + * @param context The environmental context used to determine the activation status of a profile, must not be + * {@code null}. + * @return The list of active profiles, never {@code null}. + * @throws ProfileActivationException If the activation status of any profile could not be determined (e.g. due to + * missing values or bad syntax). + */ + List getActiveProfiles( Collection profiles, ProfileActivationContext context ) + throws ProfileActivationException; + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/FileProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/FileProfileActivator.java new file mode 100644 index 0000000000..fcd53cc3d4 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/FileProfileActivator.java @@ -0,0 +1,98 @@ +package org.apache.maven.model.profile.activator; + +/* + * 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.io.File; + +import org.apache.maven.model.Activation; +import org.apache.maven.model.ActivationFile; +import org.apache.maven.model.Profile; +import org.apache.maven.model.profile.ProfileActivationContext; +import org.apache.maven.model.profile.ProfileActivationException; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.interpolation.MapBasedValueSource; +import org.codehaus.plexus.util.interpolation.RegexBasedInterpolator; + +/** + * Determines profile activation based on the existence/absence of some file. + * + * @author Benjamin Bentmann + */ +@Component( role = ProfileActivator.class, hint = "file" ) +public class FileProfileActivator + implements ProfileActivator +{ + + public boolean isActive( Profile profile, ProfileActivationContext context ) + throws ProfileActivationException + { + boolean active = false; + + Activation activation = profile.getActivation(); + + if ( activation != null ) + { + ActivationFile file = activation.getFile(); + + if ( file != null ) + { + RegexBasedInterpolator interpolator = new RegexBasedInterpolator(); + interpolator.addValueSource( new MapBasedValueSource( context.getExecutionProperties() ) ); + + String existingPath = file.getExists(); + String missingPath = file.getMissing(); + + if ( StringUtils.isNotEmpty( existingPath ) ) + { + try + { + existingPath = StringUtils.replace( interpolator.interpolate( existingPath, "" ), "\\", "/" ); + } + catch ( Exception e ) + { + throw new ProfileActivationException( profile, + "Failed to interpolate file location for profile " + + profile.getId() + ": " + existingPath ); + } + active = new File( existingPath ).exists(); + } + else if ( StringUtils.isNotEmpty( missingPath ) ) + { + try + { + missingPath = StringUtils.replace( interpolator.interpolate( missingPath, "" ), "\\", "/" ); + } + catch ( Exception e ) + { + throw new ProfileActivationException( profile, + "Failed to interpolate file location for profile " + + profile.getId() + ": " + existingPath ); + } + active = !new File( missingPath ).exists(); + } + + } + } + + return active; + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/JdkVersionProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/JdkVersionProfileActivator.java new file mode 100644 index 0000000000..8824a73799 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/JdkVersionProfileActivator.java @@ -0,0 +1,219 @@ +package org.apache.maven.model.profile.activator; + +/* + * 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.Arrays; +import java.util.List; + +import org.apache.maven.model.Activation; +import org.apache.maven.model.Profile; +import org.apache.maven.model.profile.ProfileActivationContext; +import org.apache.maven.model.profile.ProfileActivationException; +import org.codehaus.plexus.component.annotations.Component; + +/** + * Determines profile activation based on the version of the current Java runtime. + * + * @author Benjamin Bentmann + */ +@Component( role = ProfileActivator.class, hint = "jdk-version" ) +public class JdkVersionProfileActivator + implements ProfileActivator +{ + + public boolean isActive( Profile profile, ProfileActivationContext context ) + throws ProfileActivationException + { + boolean active = false; + + Activation activation = profile.getActivation(); + + if ( activation != null ) + { + String jdk = activation.getJdk(); + + if ( jdk != null ) + { + String version = context.getExecutionProperties().getProperty( "java.version", "" ); + + if ( version.length() <= 0 ) + { + throw new ProfileActivationException( profile, "Failed to determine Java version for profile " + + profile.getId() ); + } + + if ( jdk.startsWith( "!" ) ) + { + active = !version.startsWith( jdk.substring( 1 ) ); + } + else if ( isRange( jdk ) ) + { + active = isInRange( version, getRange( jdk ) ); + } + else + { + active = version.startsWith( jdk ); + } + } + } + + return active; + } + + private static boolean isInRange( String value, List range ) + { + int leftRelation = getRelationOrder( value, range.get( 0 ), true ); + + if ( leftRelation == 0 ) + { + return true; + } + + if ( leftRelation < 0 ) + { + return false; + } + + return getRelationOrder( value, range.get( 1 ), false ) <= 0; + } + + private static int getRelationOrder( String value, RangeValue rangeValue, boolean isLeft ) + { + if ( rangeValue.value.length() <= 0 ) + { + return isLeft ? 1 : -1; + } + + List valueTokens = new ArrayList( Arrays.asList( value.split( "\\." ) ) ); + List rangeValueTokens = new ArrayList( Arrays.asList( rangeValue.value.split( "\\." ) ) ); + + int max = Math.max( valueTokens.size(), rangeValueTokens.size() ); + addZeroTokens( valueTokens, max ); + addZeroTokens( rangeValueTokens, max ); + + if ( value.equals( rangeValue.value ) ) + { + if ( !rangeValue.isClosed() ) + { + return isLeft ? -1 : 1; + } + return 0; + } + + for ( int i = 0; i < valueTokens.size(); i++ ) + { + int x = Integer.parseInt( valueTokens.get( i ) ); + int y = Integer.parseInt( rangeValueTokens.get( i ) ); + if ( x < y ) + { + return -1; + } + else if ( x > y ) + { + return 1; + } + } + if ( !rangeValue.isClosed() ) + { + return isLeft ? -1 : 1; + } + return 0; + } + + private static void addZeroTokens( List tokens, int max ) + { + if ( tokens.size() < max ) + { + for ( int i = 0; i < ( max - tokens.size() ); i++ ) + { + tokens.add( "0" ); + } + } + } + + private static boolean isRange( String value ) + { + return value.startsWith( "[" ) || value.startsWith( "(" ); + } + + private static List getRange( String range ) + { + List ranges = new ArrayList(); + + for ( String token : range.split( "," ) ) + { + if ( token.startsWith( "[" ) ) + { + ranges.add( new RangeValue( token.replace( "[", "" ), true ) ); + } + else if ( token.startsWith( "(" ) ) + { + ranges.add( new RangeValue( token.replace( "(", "" ), false ) ); + } + else if ( token.endsWith( "]" ) ) + { + ranges.add( new RangeValue( token.replace( "]", "" ), true ) ); + } + else if ( token.endsWith( ")" ) ) + { + ranges.add( new RangeValue( token.replace( ")", "" ), false ) ); + } + else if ( token.length() <= 0 ) + { + ranges.add( new RangeValue( "", false ) ); + } + } + if ( ranges.size() < 2 ) + { + ranges.add( new RangeValue( "99999999", false ) ); + } + return ranges; + } + + private static class RangeValue + { + private String value; + + private boolean isClosed; + + RangeValue( String value, boolean isClosed ) + { + this.value = value.trim(); + this.isClosed = isClosed; + } + + public String getValue() + { + return value; + } + + public boolean isClosed() + { + return isClosed; + } + + public String toString() + { + return value; + } + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/OperatingSystemProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/OperatingSystemProfileActivator.java new file mode 100644 index 0000000000..0832f77ddd --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/OperatingSystemProfileActivator.java @@ -0,0 +1,174 @@ +package org.apache.maven.model.profile.activator; + +/* + * 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.ActivationOS; +import org.apache.maven.model.Profile; +import org.apache.maven.model.profile.ProfileActivationContext; +import org.apache.maven.model.profile.ProfileActivationException; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.util.Os; + +/** + * Determines profile activation based on the operating system of the current runtime platform. + * + * @author Benjamin Bentmann + */ +@Component( role = ProfileActivator.class, hint = "os" ) +public class OperatingSystemProfileActivator + implements ProfileActivator +{ + + public boolean isActive( Profile profile, ProfileActivationContext context ) + throws ProfileActivationException + { + boolean active = false; + + Activation activation = profile.getActivation(); + + if ( activation != null ) + { + ActivationOS os = activation.getOs(); + + if ( os != null ) + { + active = ensureAtLeastOneNonNull( os ); + + if ( active && os.getFamily() != null ) + { + active = determineFamilyMatch( os.getFamily() ); + } + if ( active && os.getName() != null ) + { + active = determineNameMatch( os.getName() ); + } + if ( active && os.getArch() != null ) + { + active = determineArchMatch( os.getArch() ); + } + if ( active && os.getVersion() != null ) + { + active = determineVersionMatch( os.getVersion() ); + } + } + } + + return active; + } + + private boolean ensureAtLeastOneNonNull( ActivationOS os ) + { + return os.getArch() != null || os.getFamily() != null || os.getName() != null || os.getVersion() != null; + } + + private boolean determineVersionMatch( String version ) + { + String test = version; + boolean reverse = false; + + if ( test.startsWith( "!" ) ) + { + reverse = true; + test = test.substring( 1 ); + } + + boolean result = Os.isVersion( test ); + + if ( reverse ) + { + return !result; + } + else + { + return result; + } + } + + private boolean determineArchMatch( String arch ) + { + String test = arch; + boolean reverse = false; + + if ( test.startsWith( "!" ) ) + { + reverse = true; + test = test.substring( 1 ); + } + + boolean result = Os.isArch( test ); + + if ( reverse ) + { + return !result; + } + else + { + return result; + } + } + + private boolean determineNameMatch( String name ) + { + String test = name; + boolean reverse = false; + + if ( test.startsWith( "!" ) ) + { + reverse = true; + test = test.substring( 1 ); + } + + boolean result = Os.isName( test ); + + if ( reverse ) + { + return !result; + } + else + { + return result; + } + } + + private boolean determineFamilyMatch( String family ) + { + String test = family; + boolean reverse = false; + + if ( test.startsWith( "!" ) ) + { + reverse = true; + test = test.substring( 1 ); + } + + boolean result = Os.isFamily( test ); + + if ( reverse ) + { + return !result; + } + else + { + return result; + } + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/ProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/ProfileActivator.java new file mode 100644 index 0000000000..71154ecae5 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/ProfileActivator.java @@ -0,0 +1,47 @@ +package org.apache.maven.model.profile.activator; + +/* + * 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.Profile; +import org.apache.maven.model.profile.ProfileActivationContext; +import org.apache.maven.model.profile.ProfileActivationException; + +/** + * Determines whether a profile should be activated. + * + * @author Benjamin Bentmann + */ +public interface ProfileActivator +{ + + /** + * Determines whether the specified profile is active in the given activator context. + * + * @param profile The profile whose activation status should be determined, must not be {@code null}. + * @param context The environmental context used to determine the activation status of the profile, must not be + * {@code null}. + * @return {@code true} if the profile is active, {@code false} otherwise. + * @throws ProfileActivationException If the activation status of the profile could not be determined (e.g. due to + * missing values or bad syntax). + */ + boolean isActive( Profile profile, ProfileActivationContext context ) + throws ProfileActivationException; + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/PropertyProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/PropertyProfileActivator.java new file mode 100644 index 0000000000..ce6449815d --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activator/PropertyProfileActivator.java @@ -0,0 +1,112 @@ +package org.apache.maven.model.profile.activator; + +/* + * 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.ActivationProperty; +import org.apache.maven.model.Profile; +import org.apache.maven.model.profile.ProfileActivationContext; +import org.apache.maven.model.profile.ProfileActivationException; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.util.StringUtils; + +/** + * Determines profile activation based on the existence or value of some execution property. + * + * @author Benjamin Bentmann + */ +@Component( role = ProfileActivator.class, hint = "property" ) +public class PropertyProfileActivator + implements ProfileActivator +{ + + public boolean isActive( Profile profile, ProfileActivationContext context ) + throws ProfileActivationException + { + boolean active = false; + + Activation activation = profile.getActivation(); + + if ( activation != null ) + { + ActivationProperty property = activation.getProperty(); + + if ( property != null ) + { + String name = property.getName(); + boolean reverseName = false; + + if ( name == null ) + { + throw new ProfileActivationException( profile, + "The property name is required to activate the profile " + + profile.getId() ); + } + + if ( name.startsWith( "!" ) ) + { + reverseName = true; + name = name.substring( 1 ); + } + + String sysValue = context.getExecutionProperties().getProperty( name ); + + String propValue = property.getValue(); + if ( StringUtils.isNotEmpty( propValue ) ) + { + boolean reverseValue = false; + if ( propValue.startsWith( "!" ) ) + { + reverseValue = true; + propValue = propValue.substring( 1 ); + } + + // we have a value, so it has to match the system value... + boolean result = propValue.equals( sysValue ); + + if ( reverseValue ) + { + active = !result; + } + else + { + active = result; + } + } + else + { + boolean result = StringUtils.isNotEmpty( sysValue ); + + if ( reverseName ) + { + active = !result; + } + else + { + active = result; + } + } + } + } + + return active; + } + +}