You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by el...@apache.org on 2021/05/15 11:51:27 UTC

[maven] branch master updated: [MNG-6802] Fix bug in FileProfileActivator (#347)

This is an automated email from the ASF dual-hosted git repository.

elharo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/master by this push:
     new 3fabb63  [MNG-6802] Fix bug in FileProfileActivator  (#347)
3fabb63 is described below

commit 3fabb639a31d6076b1649c1a08828febabddf44a
Author: Ravil Galeyev <rg...@gmail.com>
AuthorDate: Sat May 15 13:51:15 2021 +0200

    [MNG-6802] Fix bug in FileProfileActivator  (#347)
    
    * [MNG-6802] FileProfileActivator changes exists
    
    FileProfileActivator changes FileProfileActivator.exists
    which lets flattened resolveCiFriendliesOnly depending
    fail activating profile.
    
    * [MNG-6802] Add java docs
    
    * [MNG-6802] PR comments fixes
    
    * Make ProfileActivationFilePathInterpolator a class
    * call super.tearDown() last
    
    * [MNG-6802] PR comments fixes
    
    * Get rid of reusing local variables
    * Rename file-> activationFile
    * Move if ( missing ) to try block
    * Update javadocs
    * Replace string format with concatenation
    * Replace FileReader to FileInputStream
    
    * [MNG-6802] Update javadoc
    
    * [MNG-6802] Switch to commons lang3 StringUtils
    
    * [MNG-6802] Switch to commons lang3 StringUtils
    
    * [MNG-6802] Switch to plexus-utils StringUtils back
    
    * [MNG-6802] Switch to plexus-utils StringUtils back
    
    * [MNG-6802] Resolve conflicts
    
    * [MNG-6802] Upgrade tests
    
    * [MNG-6802] Fix for windows
    
    * [MNG-6802] Remove annotation
    
    * [MNG-6802] Create a temp dir
    
    * [MNG-6802] Remove space
    
    * [MNG-6802] Small refactoring
    
    * [MNG-6802] Use JUnit5 tempDir
    
    * [MNG-6802] Use static import
    
    * [MNG-6802] Remove plexus
    
    * [MNG-6802] Remove plexus
    
    * [MNG-6802] Fix checklstyle
    
    * [MNG-6802] Restart build
    
    * [MNG-6802] Restart build
    
    * [MNG-6802] Restart build (last attempt)
    
    * [MNG-6802] Fix PR comments
    
    * [MNG-6802] Refactor try-catch
    
    * [MNG-6802] Fix comments in FileProfileActivatorTest
    
    * [MNG-6802] Use primitive
    
    * [MNG-6802] Push down path
---
 .../maven/model/building/DefaultModelBuilder.java  |  72 ++++++++++-
 .../model/building/DefaultModelBuilderFactory.java |  10 +-
 .../ProfileActivationFilePathInterpolator.java     | 103 ++++++++++++++++
 .../profile/activation/FileProfileActivator.java   |  66 ++---------
 .../building/DefaultModelBuilderFactoryTest.java   |  35 +++++-
 .../activation/FileProfileActivatorTest.java       | 131 +++++++++++++++++++++
 6 files changed, 359 insertions(+), 58 deletions(-)

diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
index 62afcd1..07480e5 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
@@ -50,6 +50,7 @@ import org.apache.maven.artifact.versioning.VersionRange;
 import org.apache.maven.building.Source;
 import org.apache.maven.feature.Features;
 import org.apache.maven.model.Activation;
+import org.apache.maven.model.ActivationFile;
 import org.apache.maven.model.Build;
 import org.apache.maven.model.Dependency;
 import org.apache.maven.model.DependencyManagement;
@@ -74,11 +75,13 @@ import org.apache.maven.model.merge.ModelMerger;
 import org.apache.maven.model.normalization.ModelNormalizer;
 import org.apache.maven.model.path.ModelPathTranslator;
 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.PluginConfigurationExpander;
 import org.apache.maven.model.plugin.ReportConfigurationExpander;
 import org.apache.maven.model.plugin.ReportingConverter;
 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.ProfileSelector;
 import org.apache.maven.model.resolution.InvalidRepositoryException;
@@ -87,6 +90,7 @@ import org.apache.maven.model.resolution.UnresolvableModelException;
 import org.apache.maven.model.resolution.WorkspaceModelResolver;
 import org.apache.maven.model.superpom.SuperPomProvider;
 import org.apache.maven.model.validation.ModelValidator;
+import org.codehaus.plexus.interpolation.InterpolationException;
 import org.codehaus.plexus.interpolation.MapBasedValueSource;
 import org.codehaus.plexus.interpolation.StringSearchInterpolator;
 import org.eclipse.sisu.Nullable;
@@ -153,6 +157,9 @@ public class DefaultModelBuilder
 
     private ModelMerger modelMerger = new FileToRawModelMerger();
 
+    @Inject
+    private ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
+
     public DefaultModelBuilder setModelProcessor( ModelProcessor modelProcessor )
     {
         this.modelProcessor = modelProcessor;
@@ -255,12 +262,19 @@ public class DefaultModelBuilder
         return this;
     }
 
+    public DefaultModelBuilder setProfileActivationFilePathInterpolator(
+            ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator )
+    {
+        this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator;
+        return this;
+    }
+
     @Override
     public DefaultTransformerContextBuilder newTransformerContextBuilder()
     {
         return new DefaultTransformerContextBuilder();
     }
-
+    
     @Override
     public ModelBuildingResult build( ModelBuildingRequest request )
         throws ModelBuildingException
@@ -401,7 +415,11 @@ public class DefaultModelBuilder
             // model normalization
             modelNormalizer.mergeDuplicates( tmpModel, request, problems );
 
-            Map<String, Activation> interpolatedActivations = getProfileActivations( tmpModel, false );
+            profileActivationContext.setProjectProperties( tmpModel.getProperties() );
+
+            Map<String, Activation> interpolatedActivations = getInterpolatedActivations( rawModel,
+                                                                                          profileActivationContext, 
+                                                                                          problems );
             injectProfileActivations( tmpModel, interpolatedActivations );
 
             // profile injection
@@ -482,6 +500,56 @@ public class DefaultModelBuilder
         return resultModel;
     }
 
+    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 ( isNotEmpty( activationFile.getExists() ) )
+            {
+                String path = activationFile.getExists();
+                String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context );
+                activationFile.setExists( absolutePath );
+            }
+            else if ( isNotEmpty( activationFile.getMissing() ) )
+            {
+                String path = activationFile.getMissing();
+                String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context );
+                activationFile.setMissing( absolutePath );
+            }
+        }
+        catch ( InterpolationException e )
+        {
+            String path = 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( isNotEmpty( activationFile.getExists() ) ? "exists" : "missing"  ) )
+                    .setException( e ) );
+        }
+    }
+
+    private static boolean isNotEmpty( String string ) 
+    {
+        return string != null && !string.isEmpty();
+    }
+
     @Override
     public ModelBuildingResult build( final ModelBuildingRequest request, final ModelBuildingResult result )
         throws ModelBuildingException
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java
index daf56ca..027db20 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java
@@ -43,6 +43,7 @@ import org.apache.maven.model.path.DefaultUrlNormalizer;
 import org.apache.maven.model.path.ModelPathTranslator;
 import org.apache.maven.model.path.ModelUrlNormalizer;
 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.plugin.DefaultPluginConfigurationExpander;
 import org.apache.maven.model.plugin.DefaultReportConfigurationExpander;
@@ -111,7 +112,13 @@ public class DefaultModelBuilderFactory
     protected ProfileActivator[] newProfileActivators()
     {
         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()
@@ -232,6 +239,7 @@ public class DefaultModelBuilderFactory
         modelBuilder.setPluginConfigurationExpander( newPluginConfigurationExpander() );
         modelBuilder.setReportConfigurationExpander( newReportConfigurationExpander() );
         modelBuilder.setReportingConverter( newReportingConverter() );
+        modelBuilder.setProfileActivationFilePathInterpolator( newProfileActivationFilePathInterpolator() );
 
         return modelBuilder;
     }
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java
new file mode 100644
index 0000000..c2f815b
--- /dev/null
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java
@@ -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 );
+    }
+}
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java
index abfa57e..923ffd2 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java
@@ -28,15 +28,13 @@ import javax.inject.Singleton;
 import org.apache.maven.model.Activation;
 import org.apache.maven.model.ActivationFile;
 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.Version;
+import org.apache.maven.model.building.ModelProblemCollector;
 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.codehaus.plexus.interpolation.AbstractValueSource;
-import org.codehaus.plexus.interpolation.MapBasedValueSource;
-import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
+import org.codehaus.plexus.interpolation.InterpolationException;
 import org.codehaus.plexus.util.StringUtils;
 
 /**
@@ -58,11 +56,12 @@ public class FileProfileActivator
 {
 
     @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;
     }
 
@@ -101,64 +100,23 @@ public class FileProfileActivator
             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
         {
-            path = interpolator.interpolate( path, "" );
+            path = profileActivationFilePathInterpolator.interpolate( path, context );
         }
-        catch ( Exception e )
+        catch ( InterpolationException e )
         {
             problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
                     .setMessage( "Failed to interpolate file location " + path + " for profile " + profile.getId()
-                                 + ": " + e.getMessage() )
+                            + ": " + e.getMessage() )
                     .setLocation( file.getLocation( missing ? "missing" : "exists" ) )
                     .setException( e ) );
             return false;
         }
 
-        path = pathTranslator.alignToBaseDirectory( path, basedir );
-
-        // replace activation value with interpolated value
-        if ( missing )
+        if ( path == null )
         {
-            file.setMissing( path );
-        }
-        else
-        {
-            file.setExists( path );
+            return false;
         }
 
         File f = new File( path );
diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java
index 5f12d6b..98e2773 100644
--- a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java
+++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java
@@ -20,10 +20,15 @@ package org.apache.maven.model.building;
  */
 
 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.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
@@ -33,9 +38,11 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 public class DefaultModelBuilderFactoryTest
 {
 
+    private static final String BASE_DIR = Paths.get( "src", "test", "resources", "poms", "factory" ).toString();
+
     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();
     }
 
     @Test
@@ -58,4 +65,30 @@ public class DefaultModelBuilderFactoryTest
         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 ) );
+    }
 }
diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java
new file mode 100644
index 0000000..acca982
--- /dev/null
+++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java
@@ -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.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Tests {@link FileProfileActivator}.
+ *
+ * @author Ravil Galeyev
+ */
+public class FileProfileActivatorTest extends AbstractProfileActivatorTest<FileProfileActivator>
+{
+
+    @TempDir
+    Path tempDir;
+
+    private final DefaultProfileActivationContext context = new DefaultProfileActivationContext();
+
+    public FileProfileActivatorTest()
+    {
+        super( FileProfileActivator.class );
+    }
+
+    @BeforeEach
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        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;
+    }
+}