[maven-invoker-plugin] branch MINVOKER-246 created (now 4382d3a)

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[maven-invoker-plugin] branch MINVOKER-246 created (now 4382d3a)

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

rfscholte pushed a change to branch MINVOKER-246
in repository https://gitbox.apache.org/repos/asf/maven-invoker-plugin.git.


      at 4382d3a  [MINVOKER-246] Support hierarchical invoker.properties

This branch includes the following new commits:

     new 4382d3a  [MINVOKER-246] Support hierarchical invoker.properties

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Reply | Threaded
Open this post in threaded view
|

[maven-invoker-plugin] 01/01: [MINVOKER-246] Support hierarchical invoker.properties

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

rfscholte pushed a commit to branch MINVOKER-246
in repository https://gitbox.apache.org/repos/asf/maven-invoker-plugin.git

commit 4382d3afdc3b97ff06627909c6762f8dc39e7798
Author: rfscholte <[hidden email]>
AuthorDate: Fri Jan 11 20:30:30 2019 +0100

    [MINVOKER-246] Support hierarchical invoker.properties
---
 src/it/invocation-group-properties/pom.xml         |  69 ++++++
 .../src/it/projects/group-1/invoker.properties     |  18 ++
 .../it/projects/group-1/sub-1/invoker.properties   |  19 ++
 .../src/it/projects/group-1/sub-1/pom.xml          |  52 +++++
 .../src/it/projects/group-1/sub-2/pom.xml          |  52 +++++
 .../it/projects/group-2/sub-1/invoker.properties   |  18 ++
 .../src/it/projects/group-2/sub-1/pom.xml          |  52 +++++
 .../src/it/projects/group-2/sub-2/pom.xml          |  52 +++++
 .../src/it/projects/invoker.properties             |  18 ++
 src/it/invocation-group-properties/verify.groovy   |  20 ++
 .../maven/plugins/invoker/AbstractInvokerMojo.java | 239 ++++++++++++++++-----
 src/site/apt/examples/invoker-properties.apt.vm    |  14 +-
 12 files changed, 567 insertions(+), 56 deletions(-)

diff --git a/src/it/invocation-group-properties/pom.xml b/src/it/invocation-group-properties/pom.xml
new file mode 100644
index 0000000..86b60d1
--- /dev/null
+++ b/src/it/invocation-group-properties/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.plugins.invoker</groupId>
+  <artifactId>invocation-project</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <description>
+    Test to check that invocations can use a different POM than the one that was selected via the pomInclude
+    parameter. This allows fine-grained control over the build of a multi-module project where the modules are
+    (intentionally) not collectively build by the reactor.
+  </description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-invoker-plugin</artifactId>
+        <version>@project.version@</version>
+        <configuration>
+          <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
+          <projectsDirectory>src/it/projects</projectsDirectory>
+          <pomIncludes>
+            <include>*/*/pom.xml</include>
+          </pomIncludes>
+          <goals>
+            <goal>compile</goal>
+          </goals>
+        </configuration>
+        <executions>
+          <execution>
+            <id>integration-test</id>
+            <phase>initialize</phase>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/src/it/invocation-group-properties/src/it/projects/group-1/invoker.properties b/src/it/invocation-group-properties/src/it/projects/group-1/invoker.properties
new file mode 100644
index 0000000..c19c711
--- /dev/null
+++ b/src/it/invocation-group-properties/src/it/projects/group-1/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+
+invoker.buildResult = failure
\ No newline at end of file
diff --git a/src/it/invocation-group-properties/src/it/projects/group-1/sub-1/invoker.properties b/src/it/invocation-group-properties/src/it/projects/group-1/sub-1/invoker.properties
new file mode 100644
index 0000000..fe3dca2
--- /dev/null
+++ b/src/it/invocation-group-properties/src/it/projects/group-1/sub-1/invoker.properties
@@ -0,0 +1,19 @@
+# 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.
+
+invoker.goals = validate
+invoker.buildResult = success
\ No newline at end of file
diff --git a/src/it/invocation-group-properties/src/it/projects/group-1/sub-1/pom.xml b/src/it/invocation-group-properties/src/it/projects/group-1/sub-1/pom.xml
new file mode 100644
index 0000000..a509339
--- /dev/null
+++ b/src/it/invocation-group-properties/src/it/projects/group-1/sub-1/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>test</groupId>
+  <artifactId>sub-1</artifactId>
+  <version>0.1-SNAPSHOT</version>
+  
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>3.0.0-M2</version>
+        <executions>
+          <execution>
+            <id>enforce</id>
+            <phase>initialize</phase>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <AlwaysFail/>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/it/invocation-group-properties/src/it/projects/group-1/sub-2/pom.xml b/src/it/invocation-group-properties/src/it/projects/group-1/sub-2/pom.xml
new file mode 100644
index 0000000..faebe94
--- /dev/null
+++ b/src/it/invocation-group-properties/src/it/projects/group-1/sub-2/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>test</groupId>
+  <artifactId>sub-2</artifactId>
+  <version>0.1-SNAPSHOT</version>
+  
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>3.0.0-M2</version>
+        <executions>
+          <execution>
+            <id>enforce</id>
+            <phase>initialize</phase>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <AlwaysFail/>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/it/invocation-group-properties/src/it/projects/group-2/sub-1/invoker.properties b/src/it/invocation-group-properties/src/it/projects/group-2/sub-1/invoker.properties
new file mode 100644
index 0000000..c19c711
--- /dev/null
+++ b/src/it/invocation-group-properties/src/it/projects/group-2/sub-1/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+
+invoker.buildResult = failure
\ No newline at end of file
diff --git a/src/it/invocation-group-properties/src/it/projects/group-2/sub-1/pom.xml b/src/it/invocation-group-properties/src/it/projects/group-2/sub-1/pom.xml
new file mode 100644
index 0000000..a509339
--- /dev/null
+++ b/src/it/invocation-group-properties/src/it/projects/group-2/sub-1/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>test</groupId>
+  <artifactId>sub-1</artifactId>
+  <version>0.1-SNAPSHOT</version>
+  
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>3.0.0-M2</version>
+        <executions>
+          <execution>
+            <id>enforce</id>
+            <phase>initialize</phase>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <AlwaysFail/>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/it/invocation-group-properties/src/it/projects/group-2/sub-2/pom.xml b/src/it/invocation-group-properties/src/it/projects/group-2/sub-2/pom.xml
new file mode 100644
index 0000000..0424a64
--- /dev/null
+++ b/src/it/invocation-group-properties/src/it/projects/group-2/sub-2/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>test</groupId>
+  <artifactId>sub-2</artifactId>
+  <version>0.1-SNAPSHOT</version>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>3.0.0-M2</version>
+        <executions>
+          <execution>
+            <id>enforce</id>
+            <phase>compile</phase>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <AlwaysFail/>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/it/invocation-group-properties/src/it/projects/invoker.properties b/src/it/invocation-group-properties/src/it/projects/invoker.properties
new file mode 100644
index 0000000..d163069
--- /dev/null
+++ b/src/it/invocation-group-properties/src/it/projects/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+
+invoker.goals = initialize
\ No newline at end of file
diff --git a/src/it/invocation-group-properties/verify.groovy b/src/it/invocation-group-properties/verify.groovy
new file mode 100644
index 0000000..7ba59ce
--- /dev/null
+++ b/src/it/invocation-group-properties/verify.groovy
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+return true
\ No newline at end of file
diff --git a/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java b/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java
index 13ab1a8..f835d7b 100644
--- a/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java
+++ b/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java
@@ -82,6 +82,9 @@ import java.io.InputStream;
 import java.io.OutputStreamWriter;
 import java.io.Reader;
 import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.util.ArrayList;
@@ -89,6 +92,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
@@ -97,6 +101,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
+import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.TreeSet;
 import java.util.concurrent.ExecutorService;
@@ -460,9 +465,14 @@ public abstract class AbstractInvokerMojo
      * Maven invocation. Any property present in the file will override the corresponding setting from the plugin
      * configuration. The values of the properties are filtered and may use expressions like
      * <code>${project.version}</code> to reference project properties or values from the parameter
-     * {@link #filterProperties}. The snippet below describes the supported properties:
-     * <p/>
+     * {@link #filterProperties}.<p/>
+     *
+     * <p>
+     * As of 3.2.0 it is possible to put this folder in any of the ancestor folders, where properties will be inherited.
+     * This way you can provide a single properties file for a group of projects
+     * </p>
      *
+     * The snippet below describes the supported properties:
      * <pre>
      * # A comma or space separated list of goals/phases to execute, may
      * # specify an empty list to execute the default goal of the IT project.
@@ -829,10 +839,8 @@ public abstract class AbstractInvokerMojo
 
         File summaryReportFile = new File( reportsDirectory, "invoker-summary.txt" );
 
-        try
+        try ( Writer writer = new BufferedWriter( new FileWriter( summaryReportFile ) ) )
         {
-            Writer writer = new BufferedWriter( new FileWriter( summaryReportFile ) );
-
             for ( int i = 0; i < buildJobs.length; i++ )
             {
                 BuildJob buildJob = buildJobs[i];
@@ -850,8 +858,6 @@ public abstract class AbstractInvokerMojo
                     writer.append( "\n" );
                 }
             }
-
-            writer.close();
         }
         catch ( IOException e )
         {
@@ -1009,7 +1015,7 @@ public abstract class AbstractInvokerMojo
         }
 
         // determine project directories to clone
-        Collection<String> dirs = new LinkedHashSet<String>();
+        Collection<String> dirs = new LinkedHashSet<>();
         for ( String projectPath : projectPaths )
         {
             if ( !new File( projectsDirectory, projectPath ).isDirectory() )
@@ -1222,6 +1228,78 @@ public abstract class AbstractInvokerMojo
         {
             actualJreVersion = SelectorUtils.getJreVersion();
         }
+        
+        final Path projectsPath = this.projectsDirectory.toPath();
+        
+        Set<Path> folderGroupSet = new HashSet<>();
+        folderGroupSet.add( Paths.get( "." ) );
+        for ( BuildJob buildJob : buildJobs )
+        {
+            Path p = Paths.get( buildJob.getProject() );
+            
+            if ( Files.isRegularFile( projectsPath.resolve( p ) ) )
+            {
+                p = p.getParent();
+            }
+            
+            if ( p != null )
+            {
+                p = p.getParent();
+            }
+            
+            while ( p != null && folderGroupSet.add( p ) )
+            {
+                p = p.getParent();
+            }
+        }
+        
+        List<Path> folderGroup = new ArrayList<>( folderGroupSet );
+        Collections.sort( folderGroup );
+
+        final Map<Path, Properties> globalInvokerProperties = new HashMap<>();
+        
+        for ( Path path : folderGroup )
+        {
+            Properties ancestorProperties = globalInvokerProperties.get( projectsPath.resolve( path ).getParent() );
+
+            Path currentInvokerProperties = projectsPath.resolve( path ).resolve( invokerPropertiesFile );
+
+            Properties currentProperties;
+            if ( Files.isRegularFile( currentInvokerProperties ) )
+            {
+                if ( ancestorProperties != null )
+                {
+                    currentProperties = new Properties( ancestorProperties );
+                    
+                }
+                else
+                {
+                    currentProperties = new Properties();
+                }
+            }
+            else
+            {
+                currentProperties = ancestorProperties;
+            }
+
+            if ( Files.isRegularFile( currentInvokerProperties ) )
+            {
+                try ( InputStream in = new FileInputStream( currentInvokerProperties.toFile() ) )
+                {
+                    currentProperties.load( in );
+                }
+                catch ( IOException e )
+                {
+                    throw new MojoExecutionException( "Failed to read invoker properties: "
+                        + currentInvokerProperties );
+                }
+            }
+            
+            if ( currentProperties != null )
+            {
+                globalInvokerProperties.put( projectsPath.resolve( path ).normalize(), currentProperties );
+            }
+        }
 
         try
         {
@@ -1238,7 +1316,10 @@ public abstract class AbstractInvokerMojo
                         {
                             try
                             {
-                                runBuild( projectsDir, job, mergedSettingsFile, javaHome, actualJreVersion );
+                                Path ancestorFolder = getAncestorFolder( projectsPath.resolve( job.getProject() ) );
+
+                                runBuild( projectsDir, job, mergedSettingsFile, javaHome, actualJreVersion,
+                                          globalInvokerProperties.get( ancestorFolder ) );
                             }
                             catch ( MojoExecutionException e )
                             {
@@ -1263,7 +1344,10 @@ public abstract class AbstractInvokerMojo
             {
                 for ( BuildJob job : buildJobs )
                 {
-                    runBuild( projectsDir, job, mergedSettingsFile, javaHome, actualJreVersion );
+                    Path ancestorFolder = getAncestorFolder( projectsPath.resolve( job.getProject() ) );
+                    
+                    runBuild( projectsDir, job, mergedSettingsFile, javaHome, actualJreVersion,
+                              globalInvokerProperties.get( ancestorFolder ) );
                 }
             }
         }
@@ -1279,6 +1363,20 @@ public abstract class AbstractInvokerMojo
             }
         }
     }
+    
+    private Path getAncestorFolder( Path p )
+    {
+        Path ancestor = p;
+        if ( Files.isRegularFile( ancestor ) )
+        {
+            ancestor = ancestor.getParent();
+        }
+        if ( ancestor != null )
+        {
+            ancestor = ancestor.getParent();
+        }
+        return ancestor;
+    }
 
     /**
      * Interpolate settings.xml file.
@@ -1489,10 +1587,11 @@ public abstract class AbstractInvokerMojo
      * @param buildJob The build job to run, must not be <code>null</code>.
      * @param settingsFile The (already interpolated) user settings file for the build, may be <code>null</code> to use
      *            the current user settings.
+     * @param globalInvokerProperties
      * @throws org.apache.maven.plugin.MojoExecutionException If the project could not be launched.
      */
     private void runBuild( File projectsDir, BuildJob buildJob, File settingsFile, File actualJavaHome,
-                           CharSequence actualJreVersion )
+                           CharSequence actualJreVersion, Properties globalInvokerProperties )
         throws MojoExecutionException
     {
         // FIXME: Think about the following code part -- START
@@ -1521,7 +1620,7 @@ public abstract class AbstractInvokerMojo
 
         getLog().info( buffer().a( "Building: " ).strong( buildJob.getProject() ).toString() );
 
-        InvokerProperties invokerProperties = getInvokerProperties( basedir );
+        InvokerProperties invokerProperties = getInvokerProperties( basedir, globalInvokerProperties );
 
         // let's set what details we can
         buildJob.setName( invokerProperties.getJobName() );
@@ -1727,11 +1826,11 @@ public abstract class AbstractInvokerMojo
 
         File reportFile = new File( reportsDirectory, "BUILD-" + safeFileName + ".xml" );
         try ( FileOutputStream fos = new FileOutputStream( reportFile );
-             Writer osw = new OutputStreamWriter( fos, buildJob.getModelEncoding() ) )
+              Writer osw = new OutputStreamWriter( fos, buildJob.getModelEncoding() ) )
         {
             BuildJobXpp3Writer writer = new BuildJobXpp3Writer();
+
             writer.write( osw, buildJob );
-            osw.close();
         }
         catch ( IOException e )
         {
@@ -2536,51 +2635,89 @@ public abstract class AbstractInvokerMojo
      * @return The invoker properties, may be empty but never <code>null</code>.
      * @throws org.apache.maven.plugin.MojoExecutionException If an I/O error occurred during reading the properties.
      */
-    private InvokerProperties getInvokerProperties( final File projectDirectory )
+    private InvokerProperties getInvokerProperties( final File projectDirectory, Properties globalInvokerProperties )
         throws MojoExecutionException
     {
-        Properties props = new Properties();
-        if ( invokerPropertiesFile != null )
+        Properties props;
+        if ( globalInvokerProperties != null )
+        {
+            props = new Properties( globalInvokerProperties );
+        }
+        else
         {
-            File propertiesFile = new File( projectDirectory, invokerPropertiesFile );
-            if ( propertiesFile.isFile() )
+            props = new Properties();
+        }
+        
+//        Path projectsSourceFolder = this.projectsDirectory.toPath();
+//        Path projectsTargetFolder;
+//        if ( cloneProjectsTo != null )
+//        {
+//            projectsTargetFolder = cloneProjectsTo.toPath();
+//        }
+//        else
+//        {
+//            projectsTargetFolder = projectsSourceFolder;
+//        }
+//        
+//        Path projectDir = projectsTargetFolder.relativize( projectDirectory.toPath() );
+//        
+//        for ( int i = 0; i < projectDir.getNameCount(); i++ )
+//        {
+//            Path subInvokerProperties;
+//            if ( i == 0 )
+//            {
+//                subInvokerProperties = projectsSourceFolder.resolve( invokerPropertiesFile );
+//            }
+//            else
+//            {
+//                subInvokerProperties =
+//                    projectsSourceFolder.resolve( projectDir.subpath( 0, i ) ).resolve( invokerPropertiesFile );
+//            }
+//            
+//            getLog().debug( "Looking for " + subInvokerProperties );
+//                
+//            if ( Files.isRegularFile( subInvokerProperties ) )
+//            {
+//                try ( InputStream in = new FileInputStream( subInvokerProperties.toFile() ) )
+//                {
+//                    props.load( in );
+//                }
+//                catch ( IOException e )
+//                {
+//                    throw new MojoExecutionException( "Failed to read invoker properties: " + subInvokerProperties );
+//                }
+//            }
+//        }
+        
+        File propertiesFile = new File( projectDirectory, invokerPropertiesFile );
+        if ( propertiesFile.isFile() )
+        {
+            try ( InputStream in = new FileInputStream( propertiesFile ) )
             {
-                InputStream in = null;
-                try
-                {
-                    in = new FileInputStream( propertiesFile );
-                    props.load( in );
-                    in.close();
-                    in = null;
-                }
-                catch ( IOException e )
-                {
-                    throw new MojoExecutionException( "Failed to read invoker properties: " + propertiesFile, e );
-                }
-                finally
-                {
-                    IOUtil.close( in );
-                }
+                props.load( in );
+            }
+            catch ( IOException e )
+            {
+                throw new MojoExecutionException( "Failed to read invoker properties: " + propertiesFile, e );
             }
+        }
 
-            Interpolator interpolator = new RegexBasedInterpolator();
-            interpolator.addValueSource( new MapBasedValueSource( getInterpolationValueSource( false ) ) );
-            // CHECKSTYLE_OFF: LineLength
-            for ( String key : props.stringPropertyNames() )
+        Interpolator interpolator = new RegexBasedInterpolator();
+        interpolator.addValueSource( new MapBasedValueSource( getInterpolationValueSource( false ) ) );
+        // CHECKSTYLE_OFF: LineLength
+        for ( String key : props.stringPropertyNames() )
+        {
+            String value = props.getProperty( key );
+            try
             {
-                String value = props.getProperty( key );
-                try
-                {
-                    value = interpolator.interpolate( value, "" );
-                }
-                catch ( InterpolationException e )
-                {
-                    throw new MojoExecutionException( "Failed to interpolate invoker properties: " + propertiesFile,
-                                                      e );
-                }
-                props.setProperty( key, value );
+                value = interpolator.interpolate( value, "" );
+            }
+            catch ( InterpolationException e )
+            {
+                throw new MojoExecutionException( "Failed to interpolate invoker properties: " + propertiesFile,
+                                                  e );
             }
-            // CHECKSTYLE_ON: LineLength
+            props.setProperty( key, value );
         }
         return new InvokerProperties( props );
     }
diff --git a/src/site/apt/examples/invoker-properties.apt.vm b/src/site/apt/examples/invoker-properties.apt.vm
index b3fb07e..f226aa9 100644
--- a/src/site/apt/examples/invoker-properties.apt.vm
+++ b/src/site/apt/examples/invoker-properties.apt.vm
@@ -31,17 +31,21 @@ Invoker Properties
   The various parameters in the plugin configuration provide a means to globally configure the goals, profiles etc.
   used to run a Maven build on the projects. However, for certain projects you might want to specify different settings.
   To avoid the hassle of multiple plugin executions, you can simply use a file named <<<invoker.properties>>> to
-  control the build settings on a per project basis. The exact name of this properties file is configurable but it needs
-  to reside in the base directory of the respective project as shown below:
+  control the build settings on a per project basis or in one of its ancestor folders to apply it for a group of projects.
+  The exact name of this properties file is configurable but it needs to reside in the base directory of the respective
+  project as shown below:
+  
 
 +------------------
 ./
 +- src/
    +- it/
-      +- test-project/
-         +- pom.xml
+      +- group-1
          +- invoker.properties
-         +- src/
+         +- test-project/
+            +- pom.xml
+            +- invoker.properties
+            +- src/
 +------------------
 
   There are only a few keys supported in this file and their names typically match the corresponding parameters in the