Author: jdcasey Date: Thu Sep 13 23:54:29 2007 New Revision: 575563 URL: http://svn.apache.org/viewvc?rev=575563&view=rev Log: Splitting this <properties/> based profile activator out of native-mojos for wider use, a la maven-common-artifact-filters.
Added: maven/sandbox/trunk/shared/maven-extra-profile-activators/ maven/sandbox/trunk/shared/maven-extra-profile-activators/pom.xml (with props) maven/sandbox/trunk/shared/maven-extra-profile-activators/src/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/maven/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/maven/shared/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/maven/shared/profiles/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivator.java (with props) maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/maven/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/maven/shared/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/maven/shared/profiles/ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivatorTest.java (with props) Added: maven/sandbox/trunk/shared/maven-extra-profile-activators/pom.xml URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/shared/maven-extra-profile-activators/pom.xml?rev=575563&view=auto ============================================================================== --- maven/sandbox/trunk/shared/maven-extra-profile-activators/pom.xml (added) +++ maven/sandbox/trunk/shared/maven-extra-profile-activators/pom.xml Thu Sep 13 23:54:29 2007 @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?><project> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-shared-components</artifactId> + <version>4</version> + </parent> + + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-extra-profile-activators</artifactId> + <version>1.0-SNAPSHOT</version> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-build-context</artifactId> + <version>2.1-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + <version>2.1-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-maven-plugin</artifactId> + <version>1.3.5</version> + <executions> + <execution> + <id>create-component-descriptor</id> + <goals> + <goal>descriptor</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file Propchange: maven/sandbox/trunk/shared/maven-extra-profile-activators/pom.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/shared/maven-extra-profile-activators/pom.xml ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivator.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivator.java?rev=575563&view=auto ============================================================================== --- maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivator.java (added) +++ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivator.java Thu Sep 13 23:54:29 2007 @@ -0,0 +1,291 @@ +package org.apache.maven.shared.profiles; + +import java.io.File; +import java.util.Iterator; +import java.util.Properties; + +import org.apache.maven.context.BuildContextManager; +import org.apache.maven.model.Model; +import org.apache.maven.model.Profile; +import org.apache.maven.profiles.activation.ProfileActivator; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.build.ProjectBuildCache; +import org.apache.maven.project.build.ProjectBuildContext; +import org.apache.maven.project.build.model.ModelLineage; +import org.codehaus.plexus.logging.LogEnabled; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.logging.console.ConsoleLogger; + +/** + * @plexus.component role="org.apache.maven.profiles.activation.ProfileActivator" + * role-hint="modelProperty" + * instantiation-strategy="per-lookup" + * + * @author jdcasey + */ +public class ModelPropertyProfileActivator + implements ProfileActivator, LogEnabled +{ + + /** + * Configured as part of the CustomActivator's setup of this ProfileActivator, before the + * CustomActivator delegates the profile-activation process to it. This IS a required element, + * and it can be reversed (negated) using a '!' prefix. Reversing the name means one of two things: + * <br/> + * <ul> + * <li>If the value configuration is null, make sure the property doesn't exist in the lineage.</li> + * <li>If the value configuration does exist, make sure the retrieved value doesn't match it.</li> + * </ul> + * + * @plexus.configuration + */ + private String name; + + /** + * Configured as part of the CustomActivator's setup of this ProfileActivator, before the + * CustomActivator delegates the profile-activation process to it. This is NOT a required element, + * and it can be reversed (negated) using a '!' prefix. + * + * @plexus.configuration + */ + private String value; + + /** + * @plexus.requirement + */ + private BuildContextManager buildContextManager; + + // initialized by the container, or lazily. + private Logger logger; + + public ModelPropertyProfileActivator() + { + // provided for Plexus activation + } + + protected ModelPropertyProfileActivator( String name, BuildContextManager buildContextManager ) + { + this.name = name; + this.buildContextManager = buildContextManager; + } + + protected ModelPropertyProfileActivator( String name, String value, BuildContextManager buildContextManager ) + { + this.name = name; + this.value = value; + this.buildContextManager = buildContextManager; + } + + public boolean canDetermineActivation( Profile profile ) + { + ProjectBuildContext projectContext = ProjectBuildContext.getProjectBuildContext( buildContextManager, false ); + + if ( checkConfigurationSanity() && ( projectContext != null ) ) + { + return projectContext.getModelLineage() != null; + } + + return false; + } + + private boolean checkConfigurationSanity() + { + return name != null; + } + + public boolean isActive( Profile profile ) + { + // currently, just make sure the name configuration is set. + if ( !checkConfigurationSanity() ) + { + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "Skipping profile: " + profile.getId() + ". Reason: modelProperty activation is missing 'name' configuration." ); + } + return false; + } + + // using the project cache to speed things up; if the project has been built already, + // we don't have to search the entire model lineage for it...parents should be + // built ahead of children, so this could be a time-saver. + ProjectBuildCache projectCache = ProjectBuildCache.read( buildContextManager ); + + ProjectBuildContext projectContext = ProjectBuildContext.getProjectBuildContext( buildContextManager, false ); + + if ( projectContext == null ) + { + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "Skipping profile: " + profile.getId() + ". Reason: projectContext is missing." ); + } + + return false; + } + + ModelLineage lineage = projectContext.getModelLineage(); + + if ( lineage == null ) + { + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "Skipping profile: " + profile.getId() + ". Reason: model lineage is missing." ); + } + + return false; + } + + String originatingId = lineage.getOriginatingModel().getId(); + + String propertyName = name; + boolean reverse = false; + + if ( propertyName.startsWith( "!" ) ) + { + reverse = true; + propertyName = propertyName.substring( 1 ); + } + + String checkValue = value; + if ( ( checkValue != null ) && checkValue.startsWith( "!" ) ) + { + reverse = true; + checkValue = checkValue.substring( 1 ); + } + + boolean matches = false; + + // iterate through the Model instances that will eventually be calculated as one + // inheritance-assembled Model, and see if we can activate the profile based on properties + // found within one of them. NOTE: iteration starts with the child POM, and goes back through + // the ancestry. + for ( Iterator it = lineage.modelIterator(); it.hasNext(); ) + { + Model model = (Model) it.next(); + MavenProject project = projectCache.getCachedProject( model.getGroupId(), model.getArtifactId(), model.getVersion() ); + File file = lineage.getFile( model ); + + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "Searching: " + model.getId() + "\nfrom file: " + file + "\nfor property: " + propertyName + "\nhaving value: " + checkValue + " (if null, only checking for property presence)." ); + } + + boolean fromProject = false; + Properties properties; + if ( project != null ) + { + properties = project.getProperties(); + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "Found MavenProject instance for: " + model.getId() + "; no need to traverse entire lineage from this point back." ); + } + } + else + { + properties = model.getProperties(); + } + + if ( properties == null ) + { + if ( fromProject ) + { + break; + } + else + { + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "no properties here. continuing down the lineage." ); + } + continue; + } + } + + String retrievedValue = properties.getProperty( propertyName ); + + if ( value != null ) + { + // local-most values win, so if the retrievedValue != null in the current POM, NEVER + // look in the parent POM for a match. + // If the retrievedValue == null, though, we need to stop looking for a match here. + if ( retrievedValue == null ) + { + if ( fromProject ) + { + break; + } + else + { + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "property not found here. continuing down the lineage." ); + } + continue; + } + } + + matches = checkValue.equals( retrievedValue ); + + // if we get here, retrievedValue != null, and we're looking at the local-most POM, so: + // + // if startsWith '!' (reverse == true) and values don't match (match == false), return true + // if NOT startsWith '!' (reverse == false) and values DO match (match == true), return true + // else return false + if ( reverse != matches ) + { + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "Searching for property-value match: matches: " + matches + "; reversed: " + reverse + "; profile: " + profile.getId() + " should be activated." ); + } + break; + } + } + // if the value is not specified, then we have to search the entire ancestry before we + // can say for certain that a property is missing. + else + { + // if startsWith '!' (reverse == true) and retrievedValue == null (true), return true + // if NOT startsWith '!' (reverse == false) and NOT retrievedValue == null (false), return true + matches = retrievedValue != null; + + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "Searching for property presence: matches: " + matches + "; reversed: " + reverse + "; stopping lineage search." ); + } + + if ( matches ) + { + break; + } + } + + // if we can't definitely say we're activating the profile, go to the next model in the + // lineage, and try again. + } + + // if we get to the end of the lineage without activating the profile, return false. + boolean result = reverse != matches; + + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "As a result of modelProperty activation in profile: " + profile.getId() + " of POM: " + originatingId + ", profile is: " + ( result ? "ACTIVE" : "INACTIVE") ); + } + + return result; + } + + protected Logger getLogger() + { + if ( logger == null ) + { + logger = new ConsoleLogger( Logger.LEVEL_DEBUG, "ModelPropertyProfileActivator:internal" ); + } + + return logger; + } + + public void enableLogging( Logger logger ) + { + this.logger = logger; + } + +} Propchange: maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivator.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/shared/maven-extra-profile-activators/src/main/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivator.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivatorTest.java URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivatorTest.java?rev=575563&view=auto ============================================================================== --- maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivatorTest.java (added) +++ maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivatorTest.java Thu Sep 13 23:54:29 2007 @@ -0,0 +1,336 @@ +package org.apache.maven.shared.profiles; + +import org.apache.maven.context.BuildContextManager; +import org.apache.maven.context.DefaultBuildContextManager; +import org.apache.maven.model.Model; +import org.apache.maven.model.Profile; +import org.apache.maven.project.build.ProjectBuildContext; +import org.apache.maven.project.build.model.DefaultModelLineage; +import org.apache.maven.project.build.model.ModelLineage; + +import java.util.Properties; + +import junit.framework.TestCase; + +public class ModelPropertyProfileActivatorTest + extends TestCase +{ + + private BuildContextManager buildContextManager; + + public void setUp() throws Exception + { + super.setUp(); + + buildContextManager = new DefaultBuildContextManager(); + } + + public void testCanDetermineActivation_ShouldReturnFalseWhenNameNotSet() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + assertFalse( new ModelPropertyProfileActivator( null, "value", buildContextManager ).canDetermineActivation( profile ) ); + } + + public void testCanDetermineActivation_ShouldReturnFalseWhenLineageNotPresent() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + assertFalse( new ModelPropertyProfileActivator( "name", buildContextManager ).canDetermineActivation( profile ) ); + } + + public void testCanDetermineActivation_ShouldReturnTrueWhenNameSetAndLineagePresent() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( new Model(), null, null ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + context.setModelLineage( lineage ); + context.store( buildContextManager ); + + assertTrue( new ModelPropertyProfileActivator( "name", buildContextManager ).canDetermineActivation( profile ) ); + } + + public void testIsActive_ShouldReturnFalseWhenNameNotSet() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + assertFalse( new ModelPropertyProfileActivator( null, "value", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnFalseWhenProjectContextIsMissing() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + assertFalse( new ModelPropertyProfileActivator( "name", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnFalseWhenModelLineageMissingFromProjectContext() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + context.store( buildContextManager ); + + assertFalse( new ModelPropertyProfileActivator( "name", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnFalseWhenNoModelsInLineageContainProperties() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( new Model(), null, null ); + + context.setModelLineage( lineage ); + + context.store( buildContextManager ); + + assertFalse( new ModelPropertyProfileActivator( "name", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnTrueWhenModelPropertyNamePresentAndValueNotConfigured() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + + Model model = new Model(); + + Properties props = new Properties(); + props.setProperty( "name", "value" ); + + model.setProperties( props ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( model, null, null ); + + context.setModelLineage( lineage ); + + context.store( buildContextManager ); + + assertTrue( new ModelPropertyProfileActivator( "name", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnFalseWhenModelPropertyNamePresentValueNotConfigedAndNameConfigNegated() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + + Model model = new Model(); + + Properties props = new Properties(); + props.setProperty( "name", "value" ); + + model.setProperties( props ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( model, null, null ); + + context.setModelLineage( lineage ); + + context.store( buildContextManager ); + + assertFalse( new ModelPropertyProfileActivator( "!name", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnTrueWhenModelPropertyNameMissingValueNotConfigedAndNameConfigNegated() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + + Model model = new Model(); + + Properties props = new Properties(); + + model.setProperties( props ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( model, null, null ); + + context.setModelLineage( lineage ); + + context.store( buildContextManager ); + + assertTrue( new ModelPropertyProfileActivator( "!name", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnTrueWhenNameAndValueMatch() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + + Model model = new Model(); + + Properties props = new Properties(); + props.setProperty( "name", "value" ); + + model.setProperties( props ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( model, null, null ); + + context.setModelLineage( lineage ); + + context.store( buildContextManager ); + + assertTrue( new ModelPropertyProfileActivator( "name", "value", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnTrueWhenNameAndValueMatchInParentModel() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + + Model model = new Model(); + + Model parentModel = new Model(); + + Properties props = new Properties(); + props.setProperty( "name", "value" ); + + parentModel.setProperties( props ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( model, null, null ); + lineage.addParent( parentModel, null, null ); + + context.setModelLineage( lineage ); + + context.store( buildContextManager ); + + assertTrue( new ModelPropertyProfileActivator( "name", "value", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnFalseWhenNameMatchesAndValueDoesntMatch() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + + Model model = new Model(); + + Properties props = new Properties(); + props.setProperty( "name", "value1" ); + + model.setProperties( props ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( model, null, null ); + + context.setModelLineage( lineage ); + + context.store( buildContextManager ); + + assertFalse( new ModelPropertyProfileActivator( "name", "value", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnTrueWhenNameNegatedAndValueDoesntMatch() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + + Model model = new Model(); + + Properties props = new Properties(); + props.setProperty( "name", "value1" ); + + model.setProperties( props ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( model, null, null ); + + context.setModelLineage( lineage ); + + context.store( buildContextManager ); + + assertTrue( new ModelPropertyProfileActivator( "!name", "value", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnTrueWhenNameNegatedAndValueDoesntMatchButValueInParentDoesMatch() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + + Model model = new Model(); + + Properties props = new Properties(); + props.setProperty( "name", "value1" ); + + model.setProperties( props ); + + Model parent = new Model(); + + Properties parentProps = new Properties(); + parentProps.setProperty( "name", "value" ); + + parent.setProperties( parentProps ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( model, null, null ); + lineage.addParent( parent, null, null ); + + context.setModelLineage( lineage ); + + context.store( buildContextManager ); + + assertTrue( new ModelPropertyProfileActivator( "!name", "value", buildContextManager ).isActive( profile ) ); + } + + public void testIsActive_ShouldReturnFalseWhenNameNegatedAndParentHasValue() + { + Profile profile = new Profile(); + profile.setId( "test-profile" ); + + ProjectBuildContext context = ProjectBuildContext.getProjectBuildContext( buildContextManager, true ); + + Model model = new Model(); + + Properties props = new Properties(); + + model.setProperties( props ); + + Model parent = new Model(); + + Properties parentProps = new Properties(); + parentProps.setProperty( "name", "value" ); + + parent.setProperties( parentProps ); + + ModelLineage lineage = new DefaultModelLineage(); + lineage.setOrigin( model, null, null ); + lineage.addParent( parent, null, null ); + + context.setModelLineage( lineage ); + + context.store( buildContextManager ); + + assertFalse( new ModelPropertyProfileActivator( "!name", buildContextManager ).isActive( profile ) ); + } + +} Propchange: maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivatorTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/sandbox/trunk/shared/maven-extra-profile-activators/src/test/java/org/apache/maven/shared/profiles/ModelPropertyProfileActivatorTest.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision"