You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sj...@apache.org on 2023/01/01 15:42:02 UTC

[maven-enforcer] branch MENFORCER-455 created (now 8784339)

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

sjaranowski pushed a change to branch MENFORCER-455
in repository https://gitbox.apache.org/repos/asf/maven-enforcer.git


      at 8784339  [MENFORCER-455] New Enforcer API

This branch includes the following new commits:

     new 8784339  [MENFORCER-455] New Enforcer API

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.



[maven-enforcer] 01/01: [MENFORCER-455] New Enforcer API

Posted by sj...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sjaranowski pushed a commit to branch MENFORCER-455
in repository https://gitbox.apache.org/repos/asf/maven-enforcer.git

commit 878433930d55b5c6734e61b72dcd74c9a5d38187
Author: Slawomir Jaranowski <s....@gmail.com>
AuthorDate: Sun Jan 1 16:30:15 2023 +0100

    [MENFORCER-455] New Enforcer API
    
    - New API based on JSR 330 components
---
 enforcer-api/pom.xml                               |  23 +++
 enforcer-api/src/custom-rule-sample/pom.xml        |  27 ++--
 .../src/main/assembly/custom-rule-sample.xml       |  19 +--
 .../enforcer/rule/api/AbstractEnforcerRule.java    |  89 +++++++++++
 .../maven/enforcer/rule/api/EnforcerLogger.java    | 110 ++++++++++++++
 .../maven/enforcer/rule/api/EnforcerRule.java      |   2 +-
 .../maven/enforcer/rule/api/EnforcerRuleBase.java  |  14 +-
 .../maven/enforcer/rule/api/EnforcerRuleError.java |  27 ++--
 .../enforcer/rule/api/EnforcerRuleException.java   |  19 ++-
 .../src/site/apt/writing-a-custom-rule.apt.vm      |  67 +++------
 enforcer-rules/pom.xml                             |  11 --
 .../enforcer => enforcer/rules}/AlwaysFail.java    |  19 ++-
 .../rules}/RequireJavaVendor.java                  |  50 ++++++-
 .../rules}/RequireNoRepositories.java              | 137 +++++++++--------
 .../rules}/utils/ArtifactMatcher.java              |   2 +-
 .../rules}/utils/ArtifactUtils.java                |   5 +-
 .../rules}/utils/DependencyVersionMap.java         |   2 +-
 .../rules}/utils/DistributionManagementCheck.java  |   2 +-
 .../rules}/utils/EnforcerRuleUtils.java            |   2 +-
 .../rules}/utils/NormalizeLineSeparatorReader.java |   2 +-
 .../rules}/utils/ParentNodeProvider.java           |   2 +-
 .../rules}/utils/ParentsVisitor.java               |   2 +-
 .../rules}/utils/PluginWrapper.java                |   2 +-
 .../plugins/enforcer/AbstractBanDependencies.java  |   2 +-
 .../enforcer/BanDependencyManagementScope.java     |   2 +-
 .../enforcer/BanDistributionManagement.java        |   2 +-
 .../maven/plugins/enforcer/BanDynamicVersions.java |   4 +-
 .../enforcer/BanTransitiveDependencies.java        |   4 +-
 .../maven/plugins/enforcer/BannedDependencies.java |   2 +-
 .../plugins/enforcer/BannedDependenciesBase.java   |   2 +-
 .../maven/plugins/enforcer/BannedPlugins.java      |   2 +-
 .../plugins/enforcer/DependencyConvergence.java    |   4 +-
 .../plugins/enforcer/RequirePluginVersions.java    |   4 +-
 .../maven/plugins/enforcer/RequireReleaseDeps.java |   4 +-
 .../plugins/enforcer/RequireTextFileChecksum.java  |   4 +-
 .../plugins/enforcer/RequireUpperBoundDeps.java    |   6 +-
 .../rules}/TestAlwaysFail.java                     |   4 +-
 .../rules}/TestRequireJavaVendor.java              |  36 ++---
 .../rules}/TestRequireNoRepositories.java          |  45 +++---
 .../rules}/utils/DependencyNodeBuilder.java        |   2 +-
 .../rules}/utils/EnforcerRuleUtilsHelper.java      |   2 +-
 .../utils/MockEnforcerExpressionEvaluator.java     |   2 +-
 .../rules}/utils/TestArtifactMatcher.java          |   4 +-
 .../utils/TestMockEnforcerExpressionEvaluator.java |   2 +-
 .../utils/TestNormalizeLineSeparatorReader.java    |   4 +-
 .../maven/plugins/enforcer/EnforcerTestUtils.java  |   5 +-
 .../enforcer/RequireUpperBoundDepsTest.java        |   2 +-
 .../plugins/enforcer/TestBannedDependencies.java   |   2 +-
 .../enforcer/TestRequirePluginVersions.java        |   2 +-
 .../plugins/enforcer/TestRequireReleaseDeps.java   |   2 +-
 .../enforcer/TestRequireReleaseVersion.java        |   2 +-
 .../enforcer/TestRequireSnapshotVersion.java       |   2 +-
 .../enforcer/TestRequireTextFileChecksum.java      |   2 +-
 maven-enforcer-plugin/pom.xml                      |  11 +-
 .../src/it/projects/always-fail-warn/verify.groovy |   2 +-
 .../src/it/projects/always-fail/pom.xml            |   4 +-
 .../verify.groovy                                  |   3 +-
 .../verify.groovy                                  |   2 +-
 .../invoker.properties                             |  18 +++
 .../mod1}/pom.xml                                  |  33 +---
 .../mod2}/pom.xml                                  |  33 +---
 .../pom.xml                                        |  14 +-
 .../verify.groovy                                  |   8 +-
 .../verify.groovy                                  |   2 +-
 .../verify.groovy                                  |   2 +-
 .../require-no-repositories_failure/verify.groovy  |   2 +-
 .../verify.groovy                                  |   2 +-
 .../verify.groovy                                  |   2 +-
 .../verify.groovy                                  |   2 +-
 .../apache/maven/plugins/enforcer/EnforceMojo.java | 166 +++++++++++++++------
 .../enforcer/internal/AbstarctEnforcerLogger.java  |  88 +++++++++++
 .../enforcer/internal/EnforcerLoggerError.java}    |  34 +++--
 .../enforcer/internal/EnforcerLoggerWarn.java      |  30 ++--
 .../enforcer/internal/EnforcerRuleCache.java       |  70 +++++++++
 .../enforcer/internal}/EnforcerRuleDesc.java       |  22 ++-
 .../enforcer/internal}/EnforcerRuleManager.java    |  52 +++++--
 .../maven/plugins/enforcer/TestEnforceMojo.java    | 121 ++++++++++-----
 .../apache/maven/plugins/enforcer/TestRule1.java}  |  11 +-
 .../apache/maven/plugins/enforcer/TestRule2.java}  |  11 +-
 .../internal}/EnforcerRuleManagerTest.java         |  84 ++++++++---
 80 files changed, 1111 insertions(+), 515 deletions(-)

diff --git a/enforcer-api/pom.xml b/enforcer-api/pom.xml
index 670716d..ff3c41b 100644
--- a/enforcer-api/pom.xml
+++ b/enforcer-api/pom.xml
@@ -48,6 +48,29 @@
 
   <build>
     <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>custom-rule</id>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <phase>pre-site</phase>
+            <configuration>
+              <outputDirectory>${project.build.directory}/custom-rule-sample</outputDirectory>
+              <escapeString>\</escapeString>
+              <resources>
+                <resource>
+                  <directory>src/custom-rule-sample</directory>
+                  <filtering>true</filtering>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-assembly-plugin</artifactId>
diff --git a/enforcer-api/src/custom-rule-sample/pom.xml b/enforcer-api/src/custom-rule-sample/pom.xml
index 5b109d3..862139c 100644
--- a/enforcer-api/src/custom-rule-sample/pom.xml
+++ b/enforcer-api/src/custom-rule-sample/pom.xml
@@ -18,46 +18,45 @@
   * under the License. 
   *
 -->
+<!-- START SNIPPET: project-pom -->
 <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/xsd/maven-4.0.0.xsd">
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
+
   <groupId>custom-rule</groupId>
   <artifactId>custom-rule-sample</artifactId>
   <packaging>jar</packaging>
   <version>1.0</version>
+
   <name>My Custom Rule</name>
   <description>This is my custom rule.</description>
+
   <properties>
     <api.version>${project.version}</api.version>
     <maven.version>3.0</maven.version>
   </properties>
+
   <dependencies>
     <dependency>
       <groupId>org.apache.maven.enforcer</groupId>
       <artifactId>enforcer-api</artifactId>
-      <version>${api.version}</version>
+      <version>\${api.version}</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-core</artifactId>
-      <version>${maven.version}</version>
+      <version>\${maven.version}</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-plugin-api</artifactId>
-      <version>${maven.version}</version>
+      <version>\${maven.version}</version>
       <scope>provided</scope>
     </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.13.2</version>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
-  <build>
-  </build>
-</project>
\ No newline at end of file
+
+</project>
+    <!-- END SNIPPET: project-pom -->
\ No newline at end of file
diff --git a/enforcer-api/src/main/assembly/custom-rule-sample.xml b/enforcer-api/src/main/assembly/custom-rule-sample.xml
index 63eb1c1..864e2dc 100644
--- a/enforcer-api/src/main/assembly/custom-rule-sample.xml
+++ b/enforcer-api/src/main/assembly/custom-rule-sample.xml
@@ -18,9 +18,9 @@
   * under the License. 
   *
 -->
-<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
+<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.1"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 https://maven.apache.org/xsd/assembly-2.1.0.xsd">
+    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.1 https://maven.apache.org/xsd/assembly-2.1.1.xsd">
   <id>sample</id>
   <includeBaseDirectory>false</includeBaseDirectory>
   <formats>
@@ -28,21 +28,8 @@
   </formats>
   <fileSets>
     <fileSet>
-      <directory>src/custom-rule-sample</directory>
+      <directory>target/custom-rule-sample</directory>
       <outputDirectory>/custom-rule-sample</outputDirectory>
     </fileSet>
   </fileSets>
-  <files>
-    <!-- filters custom-rule's pom.xml to replace 'api.version' property with the current project version -->
-    <file>
-      <source>src/custom-rule-sample/pom.xml</source>
-      <outputDirectory>/custom-rule-sample</outputDirectory>
-      <filtered>true</filtered>
-    </file>
-    <file>
-      <source>src/custom-rule-sample/usage-pom.xml</source>
-      <outputDirectory>/custom-rule-sample</outputDirectory>
-      <filtered>true</filtered>
-    </file>
-  </files>
 </assembly>
\ No newline at end of file
diff --git a/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/AbstractEnforcerRule.java b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/AbstractEnforcerRule.java
new file mode 100644
index 0000000..c472625
--- /dev/null
+++ b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/AbstractEnforcerRule.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+package org.apache.maven.enforcer.rule.api;
+
+/**
+ * Entry point for custom {@code Enforcer Rule}.
+ *
+ * @author Slawomir Jaranowski
+ * @since 3.2.0
+ */
+public abstract class AbstractEnforcerRule implements EnforcerRuleBase {
+
+    /**
+     * EnforcerLogger instance
+     */
+    private EnforcerLogger log;
+
+    /**
+     * Enforcer Rule execution level
+     */
+    private EnforcerLevel level = EnforcerLevel.ERROR;
+
+    /**
+     * Used by {@code EnforcerMojo} to inject logger instance
+     *
+     * @param log an {@link EnforcerLogger} instance
+     */
+    public void setLog(EnforcerLogger log) {
+        this.log = log;
+    }
+
+    /**
+     * Provide an {@link  EnforcerLogger} instance for Rule
+     *
+     * @return an {@link EnforcerLogger} instance
+     */
+    public EnforcerLogger getLog() {
+        return log;
+    }
+
+    /**
+     * Current Enforcer execution level
+     *
+     * @return an Enforcer execution level
+     */
+    public EnforcerLevel getLevel() {
+        return level;
+    }
+
+    /**
+     * If the rule is to be cached during session scope, whole executing of Maven build,
+     * this id is used as part of the key.
+     * <p>
+     * Rule of the same class and the same cache id will be executed once.
+     *
+     * @return id to be used by the Enforcer to determine uniqueness of cache results.
+     * Return {@code null} disable cache of rule executing.
+     */
+    public String getCacheId() {
+        return null;
+    }
+
+    /**
+     * This is the interface into the rule. This method should throw an exception
+     * containing a reason message if the rule fails the check. The plugin will
+     * then decide based on the fail flag and rule level if it should stop or just log the
+     * message as a warning.
+     *
+     * @throws EnforcerRuleException the enforcer rule exception
+     * @throws EnforcerRuleError     in order to brake a build immediately
+     */
+    public abstract void execute() throws EnforcerRuleException;
+}
diff --git a/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerLogger.java b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerLogger.java
new file mode 100644
index 0000000..64c5d0b
--- /dev/null
+++ b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerLogger.java
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+package org.apache.maven.enforcer.rule.api;
+
+import java.util.function.Supplier;
+
+/**
+ * Logger used by enforcer rule.
+ *
+ * @author Slawomir Jaranowski
+ * @since 3.2.0
+ */
+public interface EnforcerLogger {
+
+    /**
+     * Log message in {@code warn} or {@code error} level according to current rule {@link EnforcerLevel}.
+     *
+     * @param message a massage to log
+     */
+    void warnOrError(CharSequence message);
+
+    /**
+     * Log message in {@code warn} or {@code error} level according to current rule {@link EnforcerLevel}.
+     * <p>
+     * {@code messageSupplier} will be evaluate only when corresponding log level is enabled.
+     *
+     * @param messageSupplier a supplier for message to log
+     */
+    void warnOrError(Supplier<CharSequence> messageSupplier);
+
+    /**
+     * Log message in {@code debug} level.
+     *
+     * @param message a massage to log
+     */
+    void debug(CharSequence message);
+
+    /**
+     * Log message in {@code debug} level.
+     * <p>
+     * {@code messageSupplier} will be evaluate only when corresponding log level is enabled.
+     *
+     * @param messageSupplier a supplier for message to log
+     */
+    void debug(Supplier<CharSequence> messageSupplier);
+
+    /**
+     * Log message in {@code info} level.
+     *
+     * @param message a massage to log
+     */
+    void info(CharSequence message);
+
+    /**
+     * Log message in {@code info} level.
+     * <p>
+     * {@code messageSupplier} will be evaluate only when corresponding log level is enabled.
+     *
+     * @param messageSupplier a supplier for message to log
+     */
+    void info(Supplier<CharSequence> messageSupplier);
+
+    /**
+     * Log message in {@code warn} level.
+     *
+     * @param message a massage to log
+     */
+    void warn(CharSequence message);
+
+    /**
+     * Log message in {@code warn} level.
+     * <p>
+     * {@code messageSupplier} will be evaluate only when corresponding log level is enabled.
+     *
+     * @param messageSupplier a supplier for message to log
+     */
+    void warn(Supplier<CharSequence> messageSupplier);
+
+    /**
+     * Log message in {@code error} level.
+     *
+     * @param message a massage to log
+     */
+    void error(CharSequence message);
+
+    /**
+     * Log message in {@code error} level.
+     * <p>
+     * {@code messageSupplier} will be evaluate only when corresponding log level is enabled.
+     *
+     * @param messageSupplier a supplier for message to log
+     */
+    void error(Supplier<CharSequence> messageSupplier);
+}
diff --git a/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRule.java b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRule.java
index 45441b5..6f38e74 100644
--- a/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRule.java
+++ b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRule.java
@@ -26,7 +26,7 @@ import javax.annotation.Nullable;
  *
  * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
  */
-public interface EnforcerRule {
+public interface EnforcerRule extends EnforcerRuleBase {
 
     /**
      * This is the interface into the rule. This method should throw an exception
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRuleBase.java
similarity index 79%
copy from maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
copy to enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRuleBase.java
index c05c677..328c307 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
+++ b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRuleBase.java
@@ -16,8 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[WARNING] Rule 0: org.apache.maven.plugins.enforcer.AlwaysFail warned with message:' )
+package org.apache.maven.enforcer.rule.api;
 
-
- 
\ No newline at end of file
+/**
+ * Base interface for old and new API.
+ * <p>
+ * Used for internal purpose.
+ *
+ * @author Slawomir Jaranowski
+ * @since 3.2.0
+ */
+public interface EnforcerRuleBase {}
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentNodeProvider.java b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRuleError.java
similarity index 62%
copy from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentNodeProvider.java
copy to enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRuleError.java
index 0edecfa..b7d7efc 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentNodeProvider.java
+++ b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRuleError.java
@@ -16,19 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
-
-import org.eclipse.aether.graph.DependencyNode;
+package org.apache.maven.enforcer.rule.api;
 
 /**
- * Provides the information about {@link org.eclipse.aether.graph.DependencyNode} parent nodes
+ * An error occurring during the execution of a rule.
+ * Rule can inform Enforcer plugin about critical state.
+ * <p>
+ * This exception break a build immediate.
+ *
+ * @author Slawomir Jaranowski
+ * @since 3.2.0
  */
-public interface ParentNodeProvider {
+public class EnforcerRuleError extends EnforcerRuleException {
+
+    public EnforcerRuleError(String message, Throwable cause) {
+        super(message, cause);
+    }
 
-    /**
-     * Returns the parent node of the given node
-     * @param node node to get the information for
-     * @return parent node or {@code null} is no information is known
-     */
-    DependencyNode getParent(DependencyNode node);
+    public EnforcerRuleError(String message) {
+        super(message);
+    }
 }
diff --git a/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRuleException.java b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRuleException.java
index fc3d78d..a8285a5 100644
--- a/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRuleException.java
+++ b/enforcer-api/src/main/java/org/apache/maven/enforcer/rule/api/EnforcerRuleException.java
@@ -19,9 +19,10 @@
 package org.apache.maven.enforcer.rule.api;
 
 /**
- * An exception occurring during the execution of a rule. Based off of
- * EnforcerRuleException, but separated to keep the rule dependencies to a
- * minimum.
+ * An exception occurring during the execution of a rule.
+ * <p>
+ * Enforcer plugin takes decision based on configuration and {@code Enforcer Rule} level
+ * whether build should pass or fail.
  *
  * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
  */
@@ -40,7 +41,9 @@ public class EnforcerRuleException extends Exception {
      * Gets the long message.
      *
      * @return the long message
+     * @deprecated not used
      */
+    @Deprecated
     public String getLongMessage() {
         return longMessage;
     }
@@ -49,7 +52,9 @@ public class EnforcerRuleException extends Exception {
      * Gets the source.
      *
      * @return the source
+     * @deprecated not used
      */
+    @Deprecated
     public Object getSource() {
         return source;
     }
@@ -58,10 +63,12 @@ public class EnforcerRuleException extends Exception {
      * Construct a new <code>EnforcerRuleException</code> exception providing
      * the source and a short and long message.
      *
-     * @param source the source
+     * @param source       the source
      * @param shortMessage the short message
-     * @param longMessage the long message
+     * @param longMessage  the long message
+     * @deprecated {@code source} and {@code longMessage} are not used
      */
+    @Deprecated
     public EnforcerRuleException(Object source, String shortMessage, String longMessage) {
         super(shortMessage);
         this.source = source;
@@ -86,7 +93,7 @@ public class EnforcerRuleException extends Exception {
      * <code>message</code>.
      *
      * @param message the message
-     * @param cause the cause
+     * @param cause   the cause
      */
     public EnforcerRuleException(String message, Throwable cause) {
         super(message, cause);
diff --git a/enforcer-api/src/site/apt/writing-a-custom-rule.apt.vm b/enforcer-api/src/site/apt/writing-a-custom-rule.apt.vm
index b0472dd..10727d7 100644
--- a/enforcer-api/src/site/apt/writing-a-custom-rule.apt.vm
+++ b/enforcer-api/src/site/apt/writing-a-custom-rule.apt.vm
@@ -29,57 +29,24 @@ Writing a custom rule
   {{{http://maven.apache.org/plugins/maven-enforcer-plugin/}maven-enforcer-plugin}}. 
   
   Note: The files shown below may be downloaded here: {{{./custom-rule.zip}custom-rule.zip}}
+
+* Project with custom Enforcer Rule
+
+  First make a new jar project starting with the sample pom below:
   
-  [[1]] First make a new jar project starting with the sample pom below:
-  
-+---+
-<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/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>custom-rule</groupId>
-  <artifactId>custom-rule-sample</artifactId>
-  <packaging>jar</packaging>
-  <version>1.0</version>
-  <name>My Custom Rule</name>
-  <description>This is my custom rule.</description>
-  <properties>
-    <api.version>${project.version}</api.version>
-    <maven.version>${mavenPrerequisite}</maven.version>
-  </properties>
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.maven.enforcer</groupId>
-      <artifactId>enforcer-api</artifactId>
-      <version>${api.version}</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-core</artifactId>
-      <version>${maven.version}</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-plugin-api</artifactId>
-      <version>${maven.version}</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>3.8.1</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-  <build>
-  </build>
-</project>
-+---+
-  Note that the classloader is shared with the embedding <<<maven-enforcer-plugin>>> (a regular {{{https://maven.apache.org/guides/mini/guide-maven-classloading.html#Plugin_Classloaders}plugin classloader}}) 
-  and therefore the artifacts <<<org.apache.maven.enforcer:enforcer-api>>> and <<<org.apache.maven.enforcer:enforcer-rules>>> are always loaded in the same version as the embedding <<<maven-enforcer-plugin>>>.
-  Custom rule artifacts should therefore only depend on `enforcer-api` and core Maven artifacts with <<<provided>>> scope (for details refer to {{{https://issues.apache.org/jira/browse/MNG-7097}MNG-7097}}).
-  The classes available from `enforcer-rules` must not be used from custom rules, as those are not considered API and may change in backwards-incompatible ways with every `maven-enforcer` version (even minor ones).
-  
+%{snippet|id=project-pom|file=target/custom-rule-sample/pom.xml}
+
+  Note that the classloader is shared with the embedding <<<maven-enforcer-plugin>>> (a regular {{{https://maven.apache.org/guides/mini/guide-maven-classloading.html#Plugin_Classloaders}plugin classloader}})
+  and therefore the artifacts <<<org.apache.maven.enforcer:enforcer-api>>> are always loaded in the same version as the embedding <<<maven-enforcer-plugin>>>.
+
+  Custom rule artifacts should therefore only depend on <<<enforcer-api>>> and core Maven artifacts with <<<provided>>> scope (for details refer to {{{https://issues.apache.org/jira/browse/MNG-7097}MNG-7097}}).
+
+  The classes available from <<<enforcer-rules>>> must not be used from custom rules, as those are not considered API and may change in backwards-incompatible ways with every <<<maven-enforcer>>> version (even minor ones).
+
+  Another dependencies used by custom rule should be in compile scope.
+
+* Implementation of custom Enforcer Rule
+
   [[2]] Create your rule class. The rule must implement the {{{./apidocs/index.html}EnforcerRule}} interface.
    The rule can get access to components and the log via the {{{./apidocs/index.html}EnforcerRuleHelper}} interface.
    In addition, the rule must provide a setter method for each parameter allowed to be configured in the pom.xml file (like the parameter <<<shouldIfail>>> shown in point 5).
diff --git a/enforcer-rules/pom.xml b/enforcer-rules/pom.xml
index efa660b..50dcac3 100644
--- a/enforcer-rules/pom.xml
+++ b/enforcer-rules/pom.xml
@@ -127,17 +127,6 @@
         <groupId>org.eclipse.sisu</groupId>
         <artifactId>sisu-maven-plugin</artifactId>
       </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-jar-plugin</artifactId>
-        <executions>
-          <execution>
-            <goals>
-              <goal>test-jar</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
     </plugins>
   </build>
 </project>
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AlwaysFail.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/AlwaysFail.java
similarity index 75%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AlwaysFail.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/AlwaysFail.java
index 586b8ef..9ddbe41 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AlwaysFail.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/AlwaysFail.java
@@ -16,21 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.enforcer.rules;
 
+import javax.inject.Named;
+
+import org.apache.maven.enforcer.rule.api.AbstractEnforcerRule;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
-import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
 
 /**
  * Always fail. This rule is useful for testing the Enforcer configuration, or to always fail the build if a particular
  * profile is enabled.
  * @author Ben Lidgey
  */
-public class AlwaysFail extends AbstractNonCacheableEnforcerRule {
+@Named("alwaysFail")
+public final class AlwaysFail extends AbstractEnforcerRule {
+
+    private String message;
 
     @Override
-    public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException {
-        String message = getMessage();
+    public void execute() throws EnforcerRuleException {
 
         StringBuilder buf = new StringBuilder();
         if (message != null) {
@@ -39,4 +43,9 @@ public class AlwaysFail extends AbstractNonCacheableEnforcerRule {
         buf.append("Always fails!");
         throw new EnforcerRuleException(buf.toString());
     }
+
+    @Override
+    public String toString() {
+        return String.format("AlwaysFail[level=%s, message=%s]", getLevel(), message);
+    }
 }
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireJavaVendor.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/RequireJavaVendor.java
similarity index 74%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireJavaVendor.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/RequireJavaVendor.java
index 5d2d62b..805a48e 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireJavaVendor.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/RequireJavaVendor.java
@@ -16,13 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.enforcer.rules;
+
+import javax.inject.Named;
 
 import java.util.List;
 
 import org.apache.commons.lang3.SystemUtils;
+import org.apache.maven.enforcer.rule.api.AbstractEnforcerRule;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
-import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
 
 /**
  * This rule checks that the Java vendor is allowed.
@@ -31,7 +33,8 @@ import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
  * @author Tim Sijstermans
  * @since 3.0.0
  */
-public class RequireJavaVendor extends AbstractNonCacheableEnforcerRule {
+@Named("requireJavaVendor")
+public final class RequireJavaVendor extends AbstractEnforcerRule {
     /**
      * Java vendors to include. If none is defined, all are included.
      *
@@ -43,10 +46,39 @@ public class RequireJavaVendor extends AbstractNonCacheableEnforcerRule {
      */
     private List<String> excludes;
 
+    /**
+     * A message used if the rule fails.
+     */
+    private String message;
+
+    /**
+     * The Java Vendor not changed during one Maven session,
+     * so can be cached.
+     *
+     * @return a cache id
+     */
+    @Override
+    public String getCacheId() {
+        String result = "";
+
+        if (includes != null) {
+            result += "" + includes.hashCode();
+        }
+
+        if (excludes != null) {
+            result += "" + excludes.hashCode();
+        }
+
+        if (message != null) {
+            result += "" + message.hashCode();
+        }
+
+        return result;
+    }
+
     @Override
-    public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException {
+    public void execute() throws EnforcerRuleException {
         if (excludes != null && excludes.contains(SystemUtils.JAVA_VENDOR)) {
-            String message = getMessage();
             if (message == null) {
                 message = String.format(
                         "%s is an excluded Required Java Vendor (JAVA_HOME=%s)",
@@ -54,7 +86,6 @@ public class RequireJavaVendor extends AbstractNonCacheableEnforcerRule {
             }
             throw new EnforcerRuleException(message);
         } else if (includes != null && !includes.contains(SystemUtils.JAVA_VENDOR)) {
-            String message = getMessage();
             if (message == null) {
                 message = String.format(
                         "%s is not an included Required Java Vendor (JAVA_HOME=%s)",
@@ -94,4 +125,11 @@ public class RequireJavaVendor extends AbstractNonCacheableEnforcerRule {
     public void setIncludes(List<String> theIncludes) {
         this.includes = theIncludes;
     }
+
+    @Override
+    public String toString() {
+        return String.format(
+                "RequireJavaVendor[level=%s, message=%s, includes=%s, excludes=%s]",
+                getLevel(), message, includes, excludes);
+    }
 }
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireNoRepositories.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/RequireNoRepositories.java
similarity index 52%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireNoRepositories.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/RequireNoRepositories.java
index 8e58777..4c63af5 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireNoRepositories.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/RequireNoRepositories.java
@@ -16,20 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.enforcer.rules;
+
+import javax.inject.Inject;
+import javax.inject.Named;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
+import org.apache.maven.enforcer.rule.api.AbstractEnforcerRule;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
-import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.model.Model;
 import org.apache.maven.model.Repository;
-import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
-import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 import org.codehaus.plexus.util.StringUtils;
 
 /**
@@ -37,7 +39,9 @@ import org.codehaus.plexus.util.StringUtils;
  *
  * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
  */
-public class RequireNoRepositories extends AbstractNonCacheableEnforcerRule {
+@Named("requireNoRepositories")
+public final class RequireNoRepositories extends AbstractEnforcerRule {
+
     private static final String VERSION = " version:";
 
     /**
@@ -78,104 +82,105 @@ public class RequireNoRepositories extends AbstractNonCacheableEnforcerRule {
     /**
      * Whether to allow plugin repositories which only resolve snapshots. By default they are banned.
      *
-     * @see {@link #setAllowSnapshotPluginRepositories(boolean)}
+     * @see #setAllowSnapshotPluginRepositories(boolean)
      */
     private boolean allowSnapshotPluginRepositories = false;
 
-    public final void setBanRepositories(boolean banRepositories) {
+    private String message;
+
+    private final MavenSession session;
+
+    @Inject
+    public RequireNoRepositories(MavenSession session) {
+        this.session = Objects.requireNonNull(session);
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public void setBanRepositories(boolean banRepositories) {
         this.banRepositories = banRepositories;
     }
 
-    public final void setBanPluginRepositories(boolean banPluginRepositories) {
+    public void setBanPluginRepositories(boolean banPluginRepositories) {
         this.banPluginRepositories = banPluginRepositories;
     }
 
-    public final void setAllowedRepositories(List<String> allowedRepositories) {
+    public void setAllowedRepositories(List<String> allowedRepositories) {
         this.allowedRepositories = allowedRepositories;
     }
 
-    public final void setAllowedPluginRepositories(List<String> allowedPluginRepositories) {
+    public void setAllowedPluginRepositories(List<String> allowedPluginRepositories) {
         this.allowedPluginRepositories = allowedPluginRepositories;
     }
 
-    public final void setAllowSnapshotRepositories(boolean allowSnapshotRepositories) {
+    public void setAllowSnapshotRepositories(boolean allowSnapshotRepositories) {
         this.allowSnapshotRepositories = allowSnapshotRepositories;
     }
 
-    public final void setAllowSnapshotPluginRepositories(boolean allowSnapshotPluginRepositories) {
+    public void setAllowSnapshotPluginRepositories(boolean allowSnapshotPluginRepositories) {
         this.allowSnapshotPluginRepositories = allowSnapshotPluginRepositories;
     }
 
     @Override
-    public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException {
-        Log logger = helper.getLog();
+    public void execute() throws EnforcerRuleException {
 
-        MavenSession session;
-        try {
-            session = (MavenSession) helper.evaluate("${session}");
+        List<MavenProject> sortedProjects = session.getProjectDependencyGraph().getSortedProjects();
 
-            List<MavenProject> sortedProjects =
-                    session.getProjectDependencyGraph().getSortedProjects();
-
-            List<Model> models = new ArrayList<>();
-            for (MavenProject mavenProject : sortedProjects) {
-                logger.debug("Scanning project: " + mavenProject.getGroupId() + ":" + mavenProject.getArtifactId()
-                        + VERSION + mavenProject.getVersion());
-                models.add(mavenProject.getOriginalModel());
-            }
+        List<Model> models = new ArrayList<>();
+        for (MavenProject mavenProject : sortedProjects) {
+            getLog().debug("Scanning project: " + mavenProject.getGroupId() + ":" + mavenProject.getArtifactId()
+                    + VERSION + mavenProject.getVersion());
+            models.add(mavenProject.getOriginalModel());
+        }
 
-            List<Model> badModels = new ArrayList<>();
-
-            StringBuilder newMsg = new StringBuilder();
-            newMsg.append("Some poms have repositories defined:" + System.lineSeparator());
-
-            for (Model model : models) {
-                if (banRepositories) {
-                    List<Repository> repos = model.getRepositories();
-                    if (repos != null && !repos.isEmpty()) {
-                        List<String> bannedRepos =
-                                findBannedRepositories(repos, allowedRepositories, allowSnapshotRepositories);
-                        if (!bannedRepos.isEmpty()) {
-                            badModels.add(model);
-                            newMsg.append(model.getGroupId() + ":" + model.getArtifactId() + VERSION
-                                    + model.getVersion() + " has repositories " + bannedRepos);
-                        }
+        List<Model> badModels = new ArrayList<>();
+
+        StringBuilder newMsg = new StringBuilder();
+        newMsg.append("Some poms have repositories defined:" + System.lineSeparator());
+
+        for (Model model : models) {
+            if (banRepositories) {
+                List<Repository> repos = model.getRepositories();
+                if (repos != null && !repos.isEmpty()) {
+                    List<String> bannedRepos =
+                            findBannedRepositories(repos, allowedRepositories, allowSnapshotRepositories);
+                    if (!bannedRepos.isEmpty()) {
+                        badModels.add(model);
+                        newMsg.append(model.getGroupId() + ":" + model.getArtifactId() + VERSION + model.getVersion()
+                                + " has repositories " + bannedRepos);
                     }
                 }
-                if (banPluginRepositories) {
-                    List<Repository> repos = model.getPluginRepositories();
-                    if (repos != null && !repos.isEmpty()) {
-                        List<String> bannedRepos = findBannedRepositories(
-                                repos, allowedPluginRepositories, allowSnapshotPluginRepositories);
-                        if (!bannedRepos.isEmpty()) {
-                            badModels.add(model);
-                            newMsg.append(model.getGroupId() + ":" + model.getArtifactId() + VERSION
-                                    + model.getVersion() + " has plugin repositories " + bannedRepos);
-                        }
+            }
+            if (banPluginRepositories) {
+                List<Repository> repos = model.getPluginRepositories();
+                if (repos != null && !repos.isEmpty()) {
+                    List<String> bannedRepos =
+                            findBannedRepositories(repos, allowedPluginRepositories, allowSnapshotPluginRepositories);
+                    if (!bannedRepos.isEmpty()) {
+                        badModels.add(model);
+                        newMsg.append(model.getGroupId() + ":" + model.getArtifactId() + VERSION + model.getVersion()
+                                + " has plugin repositories " + bannedRepos);
                     }
                 }
             }
+        }
 
-            // if anything was found, log it then append the
-            // optional message.
-            if (!badModels.isEmpty()) {
-                String message = getMessage();
-                if (StringUtils.isNotEmpty(message)) {
-                    newMsg.append(message);
-                }
-
-                throw new EnforcerRuleException(newMsg.toString());
+        // if anything was found, log it then append the
+        // optional message.
+        if (!badModels.isEmpty()) {
+            if (StringUtils.isNotEmpty(message)) {
+                newMsg.append(message);
             }
 
-        } catch (ExpressionEvaluationException e) {
-            throw new EnforcerRuleException(e.getLocalizedMessage());
+            throw new EnforcerRuleException(newMsg.toString());
         }
     }
 
     /**
-     *
-     * @param repos all repositories, never {@code null}
-     * @param allowedRepos allowed repositories, never {@code null}
+     * @param repos          all repositories, never {@code null}
+     * @param allowedRepos   allowed repositories, never {@code null}
      * @param allowSnapshots
      * @return List of banned repositoreis.
      */
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactMatcher.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ArtifactMatcher.java
similarity index 99%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactMatcher.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ArtifactMatcher.java
index c3e8653..8e20d1b 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactMatcher.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ArtifactMatcher.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import java.util.Collection;
 import java.util.HashSet;
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactUtils.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ArtifactUtils.java
similarity index 98%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactUtils.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ArtifactUtils.java
index c5c09bd..68164d3 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactUtils.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ArtifactUtils.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import java.util.Collection;
 import java.util.HashSet;
@@ -31,7 +31,6 @@ import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.model.DependencyManagement;
-import org.apache.maven.plugins.enforcer.utils.ArtifactMatcher.Pattern;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
@@ -203,6 +202,6 @@ public final class ArtifactUtils {
      * @return <code>true</code> if the artifact matches one of the patterns
      */
     static boolean compareDependency(String pattern, Artifact artifact) {
-        return new Pattern(pattern).match(artifact);
+        return new ArtifactMatcher.Pattern(pattern).match(artifact);
     }
 }
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DependencyVersionMap.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/DependencyVersionMap.java
similarity index 99%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DependencyVersionMap.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/DependencyVersionMap.java
index 5f3ce3b..01567fc 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DependencyVersionMap.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/DependencyVersionMap.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import java.util.ArrayList;
 import java.util.HashMap;
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DistributionManagementCheck.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/DistributionManagementCheck.java
similarity index 98%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DistributionManagementCheck.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/DistributionManagementCheck.java
index abaf583..e294215 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DistributionManagementCheck.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/DistributionManagementCheck.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.model.DistributionManagement;
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/EnforcerRuleUtils.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/EnforcerRuleUtils.java
similarity index 98%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/EnforcerRuleUtils.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/EnforcerRuleUtils.java
index 2283924..add55e1 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/EnforcerRuleUtils.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/EnforcerRuleUtils.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import java.util.List;
 
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/NormalizeLineSeparatorReader.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/NormalizeLineSeparatorReader.java
similarity index 99%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/NormalizeLineSeparatorReader.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/NormalizeLineSeparatorReader.java
index 50fbe02..ef7ef25 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/NormalizeLineSeparatorReader.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/NormalizeLineSeparatorReader.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import java.io.FilterReader;
 import java.io.IOException;
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentNodeProvider.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ParentNodeProvider.java
similarity index 96%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentNodeProvider.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ParentNodeProvider.java
index 0edecfa..e99c051 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentNodeProvider.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ParentNodeProvider.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import org.eclipse.aether.graph.DependencyNode;
 
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentsVisitor.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ParentsVisitor.java
similarity index 97%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentsVisitor.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ParentsVisitor.java
index 0e9bd9e..f2a39bb 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ParentsVisitor.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/ParentsVisitor.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/PluginWrapper.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/PluginWrapper.java
similarity index 99%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/PluginWrapper.java
rename to enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/PluginWrapper.java
index e1d8e51..18103fd 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/PluginWrapper.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/utils/PluginWrapper.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractBanDependencies.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractBanDependencies.java
index 5e5461f..3910f6a 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractBanDependencies.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractBanDependencies.java
@@ -23,9 +23,9 @@ import java.util.Set;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.ArtifactUtils;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.logging.Log;
-import org.apache.maven.plugins.enforcer.utils.ArtifactUtils;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 
 /**
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDependencyManagementScope.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDependencyManagementScope.java
index 7507f24..2b3dd87 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDependencyManagementScope.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDependencyManagementScope.java
@@ -25,10 +25,10 @@ import java.util.List;
 import org.apache.maven.enforcer.rule.api.EnforcerRule2;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.ArtifactMatcher;
 import org.apache.maven.model.Dependency;
 import org.apache.maven.model.DependencyManagement;
 import org.apache.maven.plugin.logging.Log;
-import org.apache.maven.plugins.enforcer.utils.ArtifactMatcher;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDistributionManagement.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDistributionManagement.java
index ee6027a..96df784 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDistributionManagement.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDistributionManagement.java
@@ -20,8 +20,8 @@ package org.apache.maven.plugins.enforcer;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.DistributionManagementCheck;
 import org.apache.maven.plugin.logging.Log;
-import org.apache.maven.plugins.enforcer.utils.DistributionManagementCheck;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDynamicVersions.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDynamicVersions.java
index 8dadd4c..aa684c0 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDynamicVersions.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanDynamicVersions.java
@@ -32,9 +32,9 @@ import java.util.stream.Collectors;
 import org.apache.maven.RepositoryUtils;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.ArtifactMatcher;
+import org.apache.maven.enforcer.rules.utils.ArtifactUtils;
 import org.apache.maven.plugin.logging.Log;
-import org.apache.maven.plugins.enforcer.utils.ArtifactMatcher;
-import org.apache.maven.plugins.enforcer.utils.ArtifactUtils;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.shared.utils.logging.MessageBuilder;
 import org.apache.maven.shared.utils.logging.MessageUtils;
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanTransitiveDependencies.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanTransitiveDependencies.java
index 50beb20..7d96582 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanTransitiveDependencies.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanTransitiveDependencies.java
@@ -27,9 +27,9 @@ import org.apache.maven.RepositoryUtils;
 import org.apache.maven.enforcer.rule.api.EnforcerRule;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.ArtifactMatcher;
+import org.apache.maven.enforcer.rules.utils.ArtifactUtils;
 import org.apache.maven.execution.MavenSession;
-import org.apache.maven.plugins.enforcer.utils.ArtifactMatcher;
-import org.apache.maven.plugins.enforcer.utils.ArtifactUtils;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 import org.eclipse.aether.artifact.ArtifactTypeRegistry;
 import org.eclipse.aether.graph.Dependency;
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java
index e65464e..6d6596d 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java
@@ -19,7 +19,7 @@
 package org.apache.maven.plugins.enforcer;
 
 import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugins.enforcer.utils.ArtifactUtils;
+import org.apache.maven.enforcer.rules.utils.ArtifactUtils;
 
 /**
  * This rule checks that lists of dependencies are not included.
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependenciesBase.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependenciesBase.java
index db16b61..e7776ac 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependenciesBase.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependenciesBase.java
@@ -24,8 +24,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.ArtifactUtils;
 import org.apache.maven.execution.MavenSession;
-import org.apache.maven.plugins.enforcer.utils.ArtifactUtils;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 import org.eclipse.aether.graph.DependencyNode;
 
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedPlugins.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedPlugins.java
index 03deb7c..73db174 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedPlugins.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedPlugins.java
@@ -21,8 +21,8 @@ package org.apache.maven.plugins.enforcer;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.ArtifactUtils;
 import org.apache.maven.execution.MavenSession;
-import org.apache.maven.plugins.enforcer.utils.ArtifactUtils;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 
 /**
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/DependencyConvergence.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/DependencyConvergence.java
index 1214930..7d8503b 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/DependencyConvergence.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/DependencyConvergence.java
@@ -25,9 +25,9 @@ import java.util.List;
 import org.apache.maven.enforcer.rule.api.EnforcerRule;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.ArtifactUtils;
+import org.apache.maven.enforcer.rules.utils.DependencyVersionMap;
 import org.apache.maven.plugin.logging.Log;
-import org.apache.maven.plugins.enforcer.utils.ArtifactUtils;
-import org.apache.maven.plugins.enforcer.utils.DependencyVersionMap;
 import org.eclipse.aether.collection.DependencyCollectionContext;
 import org.eclipse.aether.collection.DependencySelector;
 import org.eclipse.aether.graph.Dependency;
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequirePluginVersions.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequirePluginVersions.java
index 429adce..eb75161 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequirePluginVersions.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequirePluginVersions.java
@@ -37,6 +37,8 @@ import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException
 import org.apache.maven.artifact.versioning.VersionRange;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.EnforcerRuleUtils;
+import org.apache.maven.enforcer.rules.utils.PluginWrapper;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.lifecycle.DefaultLifecycles;
 import org.apache.maven.lifecycle.Lifecycle;
@@ -56,8 +58,6 @@ import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.plugin.version.PluginVersionNotFoundException;
 import org.apache.maven.plugin.version.PluginVersionResolutionException;
-import org.apache.maven.plugins.enforcer.utils.EnforcerRuleUtils;
-import org.apache.maven.plugins.enforcer.utils.PluginWrapper;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.rtinfo.RuntimeInformation;
 import org.apache.maven.settings.Settings;
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireReleaseDeps.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireReleaseDeps.java
index f78ff3a..3875a7d 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireReleaseDeps.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireReleaseDeps.java
@@ -24,12 +24,12 @@ import java.util.Set;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
-import org.apache.maven.plugins.enforcer.utils.ArtifactUtils;
+import org.apache.maven.enforcer.rules.utils.ArtifactUtils;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 
 import static java.util.Optional.ofNullable;
-import static org.apache.maven.plugins.enforcer.utils.ArtifactUtils.matchDependencyArtifact;
+import static org.apache.maven.enforcer.rules.utils.ArtifactUtils.matchDependencyArtifact;
 
 /**
  * This rule checks that no snapshots are included.
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireTextFileChecksum.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireTextFileChecksum.java
index 7d3a31e..17dfcd2 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireTextFileChecksum.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireTextFileChecksum.java
@@ -28,8 +28,8 @@ import org.apache.commons.io.input.ReaderInputStream;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
-import org.apache.maven.plugins.enforcer.utils.NormalizeLineSeparatorReader;
-import org.apache.maven.plugins.enforcer.utils.NormalizeLineSeparatorReader.LineSeparator;
+import org.apache.maven.enforcer.rules.utils.NormalizeLineSeparatorReader;
+import org.apache.maven.enforcer.rules.utils.NormalizeLineSeparatorReader.LineSeparator;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 
 /**
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDeps.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDeps.java
index 9369743..acbcec6 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDeps.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDeps.java
@@ -30,10 +30,10 @@ import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
 import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.ArtifactUtils;
+import org.apache.maven.enforcer.rules.utils.ParentNodeProvider;
+import org.apache.maven.enforcer.rules.utils.ParentsVisitor;
 import org.apache.maven.plugin.logging.Log;
-import org.apache.maven.plugins.enforcer.utils.ArtifactUtils;
-import org.apache.maven.plugins.enforcer.utils.ParentNodeProvider;
-import org.apache.maven.plugins.enforcer.utils.ParentsVisitor;
 import org.apache.maven.shared.utils.logging.MessageUtils;
 import org.eclipse.aether.graph.DependencyNode;
 import org.eclipse.aether.graph.DependencyVisitor;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestAlwaysFail.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/TestAlwaysFail.java
similarity index 93%
rename from enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestAlwaysFail.java
rename to enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/TestAlwaysFail.java
index f458dc3..6f2d245 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestAlwaysFail.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/TestAlwaysFail.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.enforcer.rules;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.junit.jupiter.api.Test;
@@ -36,7 +36,7 @@ public class TestAlwaysFail {
         final AlwaysFail rule = new AlwaysFail();
         try {
             // execute rule -- should throw EnforcerRuleException
-            rule.execute(EnforcerTestUtils.getHelper());
+            rule.execute();
             fail("Should throw EnforcerRuleException");
         } catch (EnforcerRuleException e) {
             assertNotNull(e.getMessage());
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireJavaVendor.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/TestRequireJavaVendor.java
similarity index 73%
rename from enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireJavaVendor.java
rename to enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/TestRequireJavaVendor.java
index c4153dd..4c2f733 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireJavaVendor.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/TestRequireJavaVendor.java
@@ -16,17 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.enforcer.rules;
 
 import java.util.Arrays;
 import java.util.Collections;
 
 import org.apache.commons.lang3.SystemUtils;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
-import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 /**
@@ -48,18 +48,16 @@ class TestRequireJavaVendor {
     void matchingInclude() throws EnforcerRuleException {
         // Set the required vendor to the current system vendor
         underTest.setIncludes(Collections.singletonList(SystemUtils.JAVA_VENDOR));
-        final EnforcerRuleHelper helper = EnforcerTestUtils.getHelper();
-        underTest.execute(helper);
-        // No assert and no expected exception because this test should not fail
+
+        assertThatCode(() -> underTest.execute()).doesNotThrowAnyException();
     }
 
     @Test
     void nonMatchingInclude() {
         // Set the included vendor to something irrelevant
         underTest.setIncludes(Collections.singletonList(NON_MATCHING_VENDOR));
-        final EnforcerRuleHelper helper = EnforcerTestUtils.getHelper();
 
-        assertThatThrownBy(() -> underTest.execute(helper))
+        assertThatThrownBy(() -> underTest.execute())
                 .isInstanceOf(EnforcerRuleException.class)
                 .hasMessage(
                         "%s is not an included Required Java Vendor (JAVA_HOME=%s)",
@@ -70,9 +68,8 @@ class TestRequireJavaVendor {
     void matchingExclude() {
         // Set the excluded vendor to current vendor name
         underTest.setExcludes(Collections.singletonList(SystemUtils.JAVA_VENDOR));
-        final EnforcerRuleHelper helper = EnforcerTestUtils.getHelper();
 
-        assertThatThrownBy(() -> underTest.execute(helper))
+        assertThatThrownBy(() -> underTest.execute())
                 .isInstanceOf(EnforcerRuleException.class)
                 .hasMessage(
                         "%s is an excluded Required Java Vendor (JAVA_HOME=%s)",
@@ -83,18 +80,16 @@ class TestRequireJavaVendor {
     void nonMatchingExclude() throws EnforcerRuleException {
         // Set the excluded vendor to something nonsensical
         underTest.setExcludes(Collections.singletonList(NON_MATCHING_VENDOR));
-        final EnforcerRuleHelper helper = EnforcerTestUtils.getHelper();
-        underTest.execute(helper);
-        // No assert and no expected exception because this test should not fail
+
+        assertThatCode(() -> underTest.execute()).doesNotThrowAnyException();
     }
 
     @Test
     void matchingIncludeAndMatchingExclude() {
         underTest.setExcludes(Collections.singletonList(SystemUtils.JAVA_VENDOR));
         underTest.setIncludes(Collections.singletonList(SystemUtils.JAVA_VENDOR));
-        final EnforcerRuleHelper helper = EnforcerTestUtils.getHelper();
 
-        assertThatThrownBy(() -> underTest.execute(helper))
+        assertThatThrownBy(() -> underTest.execute())
                 .isInstanceOf(EnforcerRuleException.class)
                 .hasMessage(
                         "%s is an excluded Required Java Vendor (JAVA_HOME=%s)",
@@ -105,9 +100,8 @@ class TestRequireJavaVendor {
     void matchAnyExclude() {
         // Set a bunch of excluded vendors
         underTest.setExcludes(Arrays.asList(SystemUtils.JAVA_VENDOR, SystemUtils.JAVA_VENDOR + "modified"));
-        final EnforcerRuleHelper helper = EnforcerTestUtils.getHelper();
 
-        assertThatThrownBy(() -> underTest.execute(helper))
+        assertThatThrownBy(() -> underTest.execute())
                 .isInstanceOf(EnforcerRuleException.class)
                 .hasMessage(
                         "%s is an excluded Required Java Vendor (JAVA_HOME=%s)",
@@ -118,15 +112,13 @@ class TestRequireJavaVendor {
     void matchAnyInclude() throws EnforcerRuleException {
         // Set a bunch of included vendors
         underTest.setIncludes(Arrays.asList(SystemUtils.JAVA_VENDOR, SystemUtils.JAVA_VENDOR + "modified"));
-        final EnforcerRuleHelper helper = EnforcerTestUtils.getHelper();
-        underTest.execute(helper);
-        // No assert and no expected exception because this test should not fail
+
+        assertThatCode(() -> underTest.execute()).doesNotThrowAnyException();
     }
 
     @Test
     void defaultRule() throws EnforcerRuleException {
-        final EnforcerRuleHelper helper = EnforcerTestUtils.getHelper();
-        underTest.execute(helper);
-        // No assert and no expected exception because this test should not fail
+
+        assertThatCode(() -> underTest.execute()).doesNotThrowAnyException();
     }
 }
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireNoRepositories.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/TestRequireNoRepositories.java
similarity index 93%
rename from enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireNoRepositories.java
rename to enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/TestRequireNoRepositories.java
index 260e691..ca8cc70 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireNoRepositories.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/TestRequireNoRepositories.java
@@ -16,20 +16,19 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.enforcer.rules;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.maven.enforcer.rule.api.EnforcerLogger;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
-import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.execution.ProjectDependencyGraph;
 import org.apache.maven.model.Model;
 import org.apache.maven.model.Repository;
 import org.apache.maven.model.RepositoryPolicy;
-import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 import org.junit.jupiter.api.BeforeEach;
@@ -46,7 +45,6 @@ import static org.mockito.Mockito.when;
  * @author <a href="mailto:khmarbaise@apache.org">Karl Heinz Marbaise</a>
  */
 public class TestRequireNoRepositories {
-    private EnforcerRuleHelper helper;
 
     private RequireNoRepositories rule;
 
@@ -55,15 +53,10 @@ public class TestRequireNoRepositories {
     @BeforeEach
     public void before() throws ExpressionEvaluationException {
         session = mock(MavenSession.class);
-        helper = mock(EnforcerRuleHelper.class);
 
-        when(helper.evaluate("${session}")).thenReturn(session);
-
-        Log log = mock(Log.class);
-        when(helper.getLog()).thenReturn(log);
-
-        rule = new RequireNoRepositories();
+        rule = new RequireNoRepositories(session);
         rule.setMessage("my message");
+        rule.setLog(mock(EnforcerLogger.class));
     }
 
     private MavenProject createMavenProject() {
@@ -171,7 +164,7 @@ public class TestRequireNoRepositories {
         MavenProject baseProject = createStandAloneProject();
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     /**
@@ -184,7 +177,7 @@ public class TestRequireNoRepositories {
             addRepository(baseProject, createRepository("repo", "http://example.com/repo"));
             setupSortedProjects(Collections.singletonList(baseProject));
 
-            rule.execute(helper);
+            rule.execute();
         });
     }
 
@@ -198,7 +191,7 @@ public class TestRequireNoRepositories {
             addPluginRepository(baseProject, createRepository("repo", "http://example.com/repo"));
             setupSortedProjects(Collections.singletonList(baseProject));
 
-            rule.execute(helper);
+            rule.execute();
         });
     }
 
@@ -214,7 +207,7 @@ public class TestRequireNoRepositories {
         addRepository(baseProject, createRepository(repositoryId, "http://example.com/repo"));
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     /**
@@ -230,7 +223,7 @@ public class TestRequireNoRepositories {
         addRepository(baseProject, createRepository(repositoryId, "http://example.com/repo"));
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     /**
@@ -243,7 +236,7 @@ public class TestRequireNoRepositories {
         MavenProject baseProject = createStandAloneProject();
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     /**
@@ -259,7 +252,7 @@ public class TestRequireNoRepositories {
         addPluginRepository(baseProject, createRepository(repositoryId, "http://example.com/repo"));
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     /**
@@ -275,7 +268,7 @@ public class TestRequireNoRepositories {
         addPluginRepository(baseProject, createRepository(repositoryId, "http://example.com/repo"));
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     /**
@@ -288,7 +281,7 @@ public class TestRequireNoRepositories {
         MavenProject baseProject = createStandAloneProject();
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     @Test
@@ -298,7 +291,7 @@ public class TestRequireNoRepositories {
             addRepository(baseProject, createSnapshotRepository("repo", "http://example.com/repo"));
             setupSortedProjects(Collections.singletonList(baseProject));
 
-            rule.execute(helper);
+            rule.execute();
         });
     }
 
@@ -311,7 +304,7 @@ public class TestRequireNoRepositories {
         addRepository(baseProject, createSnapshotRepository(repositoryId, "http://example.com/repo"));
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     @Test
@@ -323,7 +316,7 @@ public class TestRequireNoRepositories {
         addRepository(baseProject, createSnapshotRepository(repositoryId, "http://example.com/repo"));
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     @Test
@@ -336,7 +329,7 @@ public class TestRequireNoRepositories {
         addPluginRepository(baseProject, createSnapshotRepository(repositoryId, "http://example.com/repo"));
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     @Test
@@ -345,7 +338,7 @@ public class TestRequireNoRepositories {
         addEmptyRepository(baseProject);
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 
     @Test
@@ -354,6 +347,6 @@ public class TestRequireNoRepositories {
         addEmptyPluginRepository(baseProject);
         setupSortedProjects(Collections.singletonList(baseProject));
 
-        rule.execute(helper);
+        rule.execute();
     }
 }
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/DependencyNodeBuilder.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/DependencyNodeBuilder.java
similarity index 98%
rename from enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/DependencyNodeBuilder.java
rename to enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/DependencyNodeBuilder.java
index 4079523..fb3940a 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/DependencyNodeBuilder.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/DependencyNodeBuilder.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/EnforcerRuleUtilsHelper.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/EnforcerRuleUtilsHelper.java
similarity index 97%
rename from enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/EnforcerRuleUtilsHelper.java
rename to enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/EnforcerRuleUtilsHelper.java
index 207e4a7..e03ce1a 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/EnforcerRuleUtilsHelper.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/EnforcerRuleUtilsHelper.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRule;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/MockEnforcerExpressionEvaluator.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/MockEnforcerExpressionEvaluator.java
similarity index 97%
rename from enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/MockEnforcerExpressionEvaluator.java
rename to enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/MockEnforcerExpressionEvaluator.java
index 893ca70..80f47bf 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/MockEnforcerExpressionEvaluator.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/MockEnforcerExpressionEvaluator.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.MojoExecution;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/TestArtifactMatcher.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/TestArtifactMatcher.java
similarity index 98%
rename from enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/TestArtifactMatcher.java
rename to enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/TestArtifactMatcher.java
index ffdc9df..4f67e43 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/TestArtifactMatcher.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/TestArtifactMatcher.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -27,7 +27,7 @@ import org.apache.maven.artifact.handler.ArtifactHandler;
 import org.apache.maven.artifact.handler.DefaultArtifactHandler;
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 import org.apache.maven.artifact.versioning.VersionRange;
-import org.apache.maven.plugins.enforcer.utils.ArtifactMatcher.Pattern;
+import org.apache.maven.enforcer.rules.utils.ArtifactMatcher.Pattern;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/TestMockEnforcerExpressionEvaluator.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/TestMockEnforcerExpressionEvaluator.java
similarity index 97%
rename from enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/TestMockEnforcerExpressionEvaluator.java
rename to enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/TestMockEnforcerExpressionEvaluator.java
index 4a9feff..7894b25 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/TestMockEnforcerExpressionEvaluator.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/TestMockEnforcerExpressionEvaluator.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/TestNormalizeLineSeparatorReader.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/TestNormalizeLineSeparatorReader.java
similarity index 94%
rename from enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/TestNormalizeLineSeparatorReader.java
rename to enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/TestNormalizeLineSeparatorReader.java
index 30e462c..1ebfd0a 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/TestNormalizeLineSeparatorReader.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/utils/TestNormalizeLineSeparatorReader.java
@@ -16,14 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer.utils;
+package org.apache.maven.enforcer.rules.utils;
 
 import java.io.IOException;
 import java.io.Reader;
 import java.io.StringReader;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.maven.plugins.enforcer.utils.NormalizeLineSeparatorReader.LineSeparator;
+import org.apache.maven.enforcer.rules.utils.NormalizeLineSeparatorReader.LineSeparator;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerTestUtils.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerTestUtils.java
index c1ef1e2..aa3d26d 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerTestUtils.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerTestUtils.java
@@ -21,6 +21,8 @@ package org.apache.maven.plugins.enforcer;
 import java.util.Properties;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.DependencyNodeBuilder;
+import org.apache.maven.enforcer.rules.utils.MockEnforcerExpressionEvaluator;
 import org.apache.maven.execution.MavenExecutionRequest;
 import org.apache.maven.execution.MavenExecutionResult;
 import org.apache.maven.execution.MavenSession;
@@ -31,8 +33,6 @@ import org.apache.maven.plugin.MojoExecution;
 import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.logging.SystemStreamLog;
-import org.apache.maven.plugins.enforcer.utils.DependencyNodeBuilder;
-import org.apache.maven.plugins.enforcer.utils.MockEnforcerExpressionEvaluator;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.ProjectBuildingRequest;
 import org.codehaus.plexus.PlexusContainer;
@@ -58,7 +58,6 @@ import static org.mockito.Mockito.when;
 public final class EnforcerTestUtils {
 
     private static RepositorySystem REPOSITORY_SYSTEM = mock(RepositorySystem.class);
-    ;
 
     /**
      * Gets the maven session.
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDepsTest.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDepsTest.java
index ef2a11d..59be79b 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDepsTest.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/RequireUpperBoundDepsTest.java
@@ -20,7 +20,7 @@ package org.apache.maven.plugins.enforcer;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
-import org.apache.maven.plugins.enforcer.utils.DependencyNodeBuilder;
+import org.apache.maven.enforcer.rules.utils.DependencyNodeBuilder;
 import org.junit.jupiter.api.Test;
 
 import static org.hamcrest.MatcherAssert.assertThat;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestBannedDependencies.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestBannedDependencies.java
index c766334..069fb32 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestBannedDependencies.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestBannedDependencies.java
@@ -21,7 +21,7 @@ package org.apache.maven.plugins.enforcer;
 import java.io.IOException;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
-import org.apache.maven.plugins.enforcer.utils.DependencyNodeBuilder;
+import org.apache.maven.enforcer.rules.utils.DependencyNodeBuilder;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequirePluginVersions.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequirePluginVersions.java
index 4fa906f..c1bd3f1 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequirePluginVersions.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequirePluginVersions.java
@@ -25,9 +25,9 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.PluginWrapper;
 import org.apache.maven.model.Plugin;
 import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugins.enforcer.utils.PluginWrapper;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseDeps.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseDeps.java
index 3be6b31..41569e1 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseDeps.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseDeps.java
@@ -22,8 +22,8 @@ import java.io.IOException;
 import java.util.Collections;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.EnforcerRuleUtilsHelper;
 import org.apache.maven.plugin.testing.ArtifactStubFactory;
-import org.apache.maven.plugins.enforcer.utils.EnforcerRuleUtilsHelper;
 import org.apache.maven.project.MavenProject;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseVersion.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseVersion.java
index e6e3117..bf8da0b 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseVersion.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireReleaseVersion.java
@@ -22,8 +22,8 @@ import java.io.IOException;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRule;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.EnforcerRuleUtilsHelper;
 import org.apache.maven.plugin.testing.ArtifactStubFactory;
-import org.apache.maven.plugins.enforcer.utils.EnforcerRuleUtilsHelper;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireSnapshotVersion.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireSnapshotVersion.java
index f780a5f..1da0d7b 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireSnapshotVersion.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireSnapshotVersion.java
@@ -21,8 +21,8 @@ package org.apache.maven.plugins.enforcer;
 import java.io.IOException;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.enforcer.rules.utils.EnforcerRuleUtilsHelper;
 import org.apache.maven.plugin.testing.ArtifactStubFactory;
-import org.apache.maven.plugins.enforcer.utils.EnforcerRuleUtilsHelper;
 import org.apache.maven.project.MavenProject;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireTextFileChecksum.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireTextFileChecksum.java
index b1031bd..4d7fb16 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireTextFileChecksum.java
+++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireTextFileChecksum.java
@@ -24,7 +24,7 @@ import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
-import org.apache.maven.plugins.enforcer.utils.NormalizeLineSeparatorReader.LineSeparator;
+import org.apache.maven.enforcer.rules.utils.NormalizeLineSeparatorReader.LineSeparator;
 import org.codehaus.plexus.util.FileUtils;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
diff --git a/maven-enforcer-plugin/pom.xml b/maven-enforcer-plugin/pom.xml
index dffedf4..8feed4e 100644
--- a/maven-enforcer-plugin/pom.xml
+++ b/maven-enforcer-plugin/pom.xml
@@ -52,6 +52,12 @@
       <artifactId>maven-plugin-annotations</artifactId>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>1.7.36</version>
+      <scope>provided</scope>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.maven.enforcer</groupId>
@@ -62,11 +68,6 @@
       <artifactId>enforcer-rules</artifactId>
     </dependency>
 
-    <dependency>
-      <groupId>org.apache.maven.enforcer</groupId>
-      <artifactId>enforcer-rules</artifactId>
-      <type>test-jar</type>
-    </dependency>
     <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-junit-jupiter</artifactId>
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy b/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
index c05c677..4b5d6c4 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
+++ b/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
@@ -17,7 +17,7 @@
  * under the License.
  */
 File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[WARNING] Rule 0: org.apache.maven.plugins.enforcer.AlwaysFail warned with message:' )
+assert buildLog.text.contains( '[WARNING] Rule 0: org.apache.maven.enforcer.rules.AlwaysFail warned with message:' )
 
 
  
\ No newline at end of file
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail/pom.xml b/maven-enforcer-plugin/src/it/projects/always-fail/pom.xml
index 53c77c8..89127c3 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail/pom.xml
+++ b/maven-enforcer-plugin/src/it/projects/always-fail/pom.xml
@@ -43,7 +43,9 @@ under the License.
             </goals>
             <configuration>
               <rules>
-                <AlwaysFail/>
+                <alwaysFail>
+                  <message>alwaysFail test message</message>
+                </alwaysFail>
               </rules>
             </configuration>
           </execution>
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy b/maven-enforcer-plugin/src/it/projects/always-fail/verify.groovy
similarity index 83%
copy from maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
copy to maven-enforcer-plugin/src/it/projects/always-fail/verify.groovy
index c05c677..3656737 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
+++ b/maven-enforcer-plugin/src/it/projects/always-fail/verify.groovy
@@ -17,7 +17,8 @@
  * under the License.
  */
 File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[WARNING] Rule 0: org.apache.maven.plugins.enforcer.AlwaysFail warned with message:' )
+assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.enforcer.rules.AlwaysFail failed with message:' )
+assert buildLog.text.contains( 'alwaysFail test message' )
 
 
  
\ No newline at end of file
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy b/maven-enforcer-plugin/src/it/projects/always-pass/verify.groovy
similarity index 87%
copy from maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
copy to maven-enforcer-plugin/src/it/projects/always-pass/verify.groovy
index c05c677..4079a1c 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
+++ b/maven-enforcer-plugin/src/it/projects/always-pass/verify.groovy
@@ -17,7 +17,7 @@
  * under the License.
  */
 File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[WARNING] Rule 0: org.apache.maven.plugins.enforcer.AlwaysFail warned with message:' )
+assert buildLog.text.contains( '[INFO] Rule 0: org.apache.maven.plugins.enforcer.AlwaysPass executed' )
 
 
  
\ No newline at end of file
diff --git a/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/invoker.properties b/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/invoker.properties
new file mode 100644
index 0000000..2dca44c
--- /dev/null
+++ b/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/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 = -T3 verify
\ No newline at end of file
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail/pom.xml b/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/mod1/pom.xml
similarity index 55%
copy from maven-enforcer-plugin/src/it/projects/always-fail/pom.xml
copy to maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/mod1/pom.xml
index 53c77c8..0888298 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail/pom.xml
+++ b/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/mod1/pom.xml
@@ -22,33 +22,12 @@ under the License.
 <project>
   <modelVersion>4.0.0</modelVersion>
 
-  <groupId>org.apache.maven.its.enforcer</groupId>
-  <artifactId>test</artifactId>
-  <version>1.0</version>
+  <parent>
+  	<groupId>org.apache.maven.its.enforcer</groupId>
+    <artifactId>test-multimodule-project</artifactId>
+    <version>1.0</version>
+  </parent>
 
-  <description>
-  </description>
+  <artifactId>test-multimodule-mod1</artifactId>
 
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-enforcer-plugin</artifactId>
-        <version>@project.version@</version>
-        <executions>
-          <execution>
-            <id>test</id>
-            <goals>
-              <goal>enforce</goal>
-            </goals>
-            <configuration>
-              <rules>
-                <AlwaysFail/>
-              </rules>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
 </project>
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail/pom.xml b/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/mod2/pom.xml
similarity index 55%
copy from maven-enforcer-plugin/src/it/projects/always-fail/pom.xml
copy to maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/mod2/pom.xml
index 53c77c8..64dbbc9 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail/pom.xml
+++ b/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/mod2/pom.xml
@@ -22,33 +22,12 @@ under the License.
 <project>
   <modelVersion>4.0.0</modelVersion>
 
-  <groupId>org.apache.maven.its.enforcer</groupId>
-  <artifactId>test</artifactId>
-  <version>1.0</version>
+  <parent>
+  	<groupId>org.apache.maven.its.enforcer</groupId>
+    <artifactId>test-multimodule-project</artifactId>
+    <version>1.0</version>
+  </parent>
 
-  <description>
-  </description>
+  <artifactId>test-multimodule-mod2</artifactId>
 
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-enforcer-plugin</artifactId>
-        <version>@project.version@</version>
-        <executions>
-          <execution>
-            <id>test</id>
-            <goals>
-              <goal>enforce</goal>
-            </goals>
-            <configuration>
-              <rules>
-                <AlwaysFail/>
-              </rules>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
 </project>
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail/pom.xml b/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/pom.xml
similarity index 81%
copy from maven-enforcer-plugin/src/it/projects/always-fail/pom.xml
copy to maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/pom.xml
index 53c77c8..10061ce 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail/pom.xml
+++ b/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/pom.xml
@@ -23,12 +23,18 @@ under the License.
   <modelVersion>4.0.0</modelVersion>
 
   <groupId>org.apache.maven.its.enforcer</groupId>
-  <artifactId>test</artifactId>
+  <artifactId>test-multimodule-project</artifactId>
   <version>1.0</version>
+  <packaging>pom</packaging>
 
   <description>
   </description>
 
+  <modules>
+  	<module>mod1</module>
+  	<module>mod2</module>
+  </modules>
+
   <build>
     <plugins>
       <plugin>
@@ -43,7 +49,11 @@ under the License.
             </goals>
             <configuration>
               <rules>
-                <AlwaysFail/>
+                <requireJavaVendor>
+                  <excludes>
+                    <exclude>NOT-EXISTING-VENDOR</exclude>
+                  </excludes>
+                </requireJavaVendor>
               </rules>
             </configuration>
           </execution>
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy b/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/verify.groovy
similarity index 78%
copy from maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
copy to maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/verify.groovy
index c05c677..7fdcfe3 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
+++ b/maven-enforcer-plugin/src/it/projects/require-java-vendor-multi-module/verify.groovy
@@ -16,8 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[WARNING] Rule 0: org.apache.maven.plugins.enforcer.AlwaysFail warned with message:' )
 
+File buildLog = new File(basedir, 'build.log')
 
- 
\ No newline at end of file
+rulesExecuted = buildLog.readLines()
+        .findAll {it == '[INFO] Rule 0: org.apache.maven.enforcer.rules.RequireJavaVendor executed'}
+
+assert rulesExecuted.size() == 1
\ No newline at end of file
diff --git a/maven-enforcer-plugin/src/it/projects/require-no-repositories-allow-plugin-repo/verify.groovy b/maven-enforcer-plugin/src/it/projects/require-no-repositories-allow-plugin-repo/verify.groovy
index 01f63fb..cc7a56e 100644
--- a/maven-enforcer-plugin/src/it/projects/require-no-repositories-allow-plugin-repo/verify.groovy
+++ b/maven-enforcer-plugin/src/it/projects/require-no-repositories-allow-plugin-repo/verify.groovy
@@ -17,6 +17,6 @@
  * under the License.
  */
 File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.plugins.enforcer.RequireNoRepositories failed with message:' )
+assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.enforcer.rules.RequireNoRepositories failed with message:' )
 assert buildLog.text.contains( 'Some poms have repositories defined:' )
 assert buildLog.text.contains( 'org.apache.maven.its.enforcer:test version:1.0 has repositories [com.asual.maven.public]' )
diff --git a/maven-enforcer-plugin/src/it/projects/require-no-repositories-allow-repo/verify.groovy b/maven-enforcer-plugin/src/it/projects/require-no-repositories-allow-repo/verify.groovy
index 639dd56..a6a9979 100644
--- a/maven-enforcer-plugin/src/it/projects/require-no-repositories-allow-repo/verify.groovy
+++ b/maven-enforcer-plugin/src/it/projects/require-no-repositories-allow-repo/verify.groovy
@@ -17,6 +17,6 @@
  * under the License.
  */
 File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.plugins.enforcer.RequireNoRepositories failed with message:' )
+assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.enforcer.rules.RequireNoRepositories failed with message:' )
 assert buildLog.text.contains( 'Some poms have repositories defined:' )
 assert buildLog.text.contains( 'org.apache.maven.its.enforcer:test version:1.0 has plugin repositories [plugin-repo]' )
diff --git a/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure/verify.groovy b/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure/verify.groovy
index 01f63fb..cc7a56e 100644
--- a/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure/verify.groovy
+++ b/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure/verify.groovy
@@ -17,6 +17,6 @@
  * under the License.
  */
 File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.plugins.enforcer.RequireNoRepositories failed with message:' )
+assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.enforcer.rules.RequireNoRepositories failed with message:' )
 assert buildLog.text.contains( 'Some poms have repositories defined:' )
 assert buildLog.text.contains( 'org.apache.maven.its.enforcer:test version:1.0 has repositories [com.asual.maven.public]' )
diff --git a/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_allowed-plugin-repo/verify.groovy b/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_allowed-plugin-repo/verify.groovy
index 01f63fb..cc7a56e 100644
--- a/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_allowed-plugin-repo/verify.groovy
+++ b/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_allowed-plugin-repo/verify.groovy
@@ -17,6 +17,6 @@
  * under the License.
  */
 File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.plugins.enforcer.RequireNoRepositories failed with message:' )
+assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.enforcer.rules.RequireNoRepositories failed with message:' )
 assert buildLog.text.contains( 'Some poms have repositories defined:' )
 assert buildLog.text.contains( 'org.apache.maven.its.enforcer:test version:1.0 has repositories [com.asual.maven.public]' )
diff --git a/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_plugin-repositories/verify.groovy b/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_plugin-repositories/verify.groovy
index 634d4aa..8096a1d 100644
--- a/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_plugin-repositories/verify.groovy
+++ b/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_plugin-repositories/verify.groovy
@@ -17,6 +17,6 @@
  * under the License.
  */
 File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.plugins.enforcer.RequireNoRepositories failed with message:' )
+assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.enforcer.rules.RequireNoRepositories failed with message:' )
 assert buildLog.text.contains( 'Some poms have repositories defined:' )
 assert buildLog.text.contains( 'org.apache.maven.its.enforcer:test version:1.0 has plugin repositories [repo]' )
diff --git a/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_repositories/verify.groovy b/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_repositories/verify.groovy
index 01f63fb..cc7a56e 100644
--- a/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_repositories/verify.groovy
+++ b/maven-enforcer-plugin/src/it/projects/require-no-repositories_failure_repositories/verify.groovy
@@ -17,6 +17,6 @@
  * under the License.
  */
 File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.plugins.enforcer.RequireNoRepositories failed with message:' )
+assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.enforcer.rules.RequireNoRepositories failed with message:' )
 assert buildLog.text.contains( 'Some poms have repositories defined:' )
 assert buildLog.text.contains( 'org.apache.maven.its.enforcer:test version:1.0 has repositories [com.asual.maven.public]' )
diff --git a/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/EnforceMojo.java b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/EnforceMojo.java
index 24c2545..ad2a8f7 100644
--- a/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/EnforceMojo.java
+++ b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/EnforceMojo.java
@@ -25,9 +25,13 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
+import org.apache.maven.enforcer.rule.api.AbstractEnforcerRule;
 import org.apache.maven.enforcer.rule.api.EnforcerLevel;
+import org.apache.maven.enforcer.rule.api.EnforcerLogger;
 import org.apache.maven.enforcer.rule.api.EnforcerRule;
 import org.apache.maven.enforcer.rule.api.EnforcerRule2;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleBase;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleError;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
 import org.apache.maven.execution.MavenSession;
@@ -41,6 +45,11 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.plugins.enforcer.internal.EnforcerLoggerError;
+import org.apache.maven.plugins.enforcer.internal.EnforcerLoggerWarn;
+import org.apache.maven.plugins.enforcer.internal.EnforcerRuleCache;
+import org.apache.maven.plugins.enforcer.internal.EnforcerRuleDesc;
+import org.apache.maven.plugins.enforcer.internal.EnforcerRuleManager;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.configuration.DefaultPlexusConfiguration;
@@ -147,6 +156,9 @@ public class EnforceMojo extends AbstractMojo {
     @Component
     private EnforcerRuleManager enforcerRuleManager;
 
+    @Component
+    private EnforcerRuleCache ruleCache;
+
     private List<String> rulesToExecute;
 
     /**
@@ -180,6 +192,10 @@ public class EnforceMojo extends AbstractMojo {
         setRulesToExecute(rulesToExecute);
     }
 
+    private EnforcerLogger enforcerLoggerError;
+
+    private EnforcerLogger enforcerLoggerWarn;
+
     @Override
     public void execute() throws MojoExecutionException {
         Log log = this.getLog();
@@ -209,6 +225,9 @@ public class EnforceMojo extends AbstractMojo {
             }
         }
 
+        enforcerLoggerError = new EnforcerLoggerError(log);
+        enforcerLoggerWarn = new EnforcerLoggerWarn(log);
+
         // messages with warn/error flag
         Map<String, Boolean> messages = new LinkedHashMap<>();
 
@@ -225,55 +244,31 @@ public class EnforceMojo extends AbstractMojo {
         boolean hasErrors = false;
 
         // go through each rule
-        for (int i = 0; i < rulesList.size(); i++) {
+        for (int ruleIndex = 0; ruleIndex < rulesList.size(); ruleIndex++) {
 
             // prevent against empty rules
-            EnforcerRuleDesc ruleDesc = rulesList.get(i);
+            EnforcerRuleDesc ruleDesc = rulesList.get(ruleIndex);
             if (ruleDesc != null) {
-                EnforcerRule rule = ruleDesc.getRule();
+                EnforcerRuleBase rule = ruleDesc.getRule();
                 EnforcerLevel level = getLevel(rule);
-                // store the current rule for
-                // logging purposes
-                String currentRule = rule.getClass().getName();
                 try {
-                    if (ignoreCache || shouldExecute(rule)) {
-                        // execute the rule
-                        // noinspection SynchronizationOnLocalVariableOrMethodParameter
-                        synchronized (rule) {
-                            log.info("Executing rule: " + currentRule);
-                            rule.execute(helper);
-                        }
-                    }
+                    executeRule(ruleIndex, ruleDesc, helper);
+                } catch (EnforcerRuleError e) {
+                    String ruleMessage = createRuleMessage(ruleIndex, ruleDesc, EnforcerLevel.ERROR, e);
+                    throw new MojoExecutionException(ruleMessage, e);
                 } catch (EnforcerRuleException e) {
-                    // i can throw an exception
-                    // because failfast will be
-                    // false if fail is false.
+
+                    String ruleMessage = createRuleMessage(ruleIndex, ruleDesc, level, e);
+
                     if (failFast && level == EnforcerLevel.ERROR) {
-                        throw new MojoExecutionException(
-                                currentRule + " failed with message:" + System.lineSeparator() + e.getMessage(), e);
+                        throw new MojoExecutionException(ruleMessage, e);
+                    }
+
+                    if (level == EnforcerLevel.ERROR) {
+                        hasErrors = true;
+                        messages.put(ruleMessage, true);
                     } else {
-                        // log a warning in case the exception message is missing
-                        // so that the user can figure out what is going on
-                        final String exceptionMessage = e.getMessage();
-                        if (exceptionMessage != null) {
-                            log.debug("Adding " + level + " message due to exception", e);
-                        } else {
-                            log.warn("Rule " + i + ": " + currentRule + " failed without a message", e);
-                        }
-                        // add the 'failed/warned' message including exceptionMessage
-                        // which might be null in rare cases
-                        if (level == EnforcerLevel.ERROR) {
-                            hasErrors = true;
-                            messages.put(
-                                    "Rule " + i + ": " + currentRule + " failed with message:" + System.lineSeparator()
-                                            + exceptionMessage,
-                                    true);
-                        } else {
-                            messages.put(
-                                    "Rule " + i + ": " + currentRule + " warned with message:" + System.lineSeparator()
-                                            + exceptionMessage,
-                                    false);
-                        }
+                        messages.put(ruleMessage, false);
                     }
                 }
             }
@@ -294,6 +289,52 @@ public class EnforceMojo extends AbstractMojo {
         }
     }
 
+    private void executeRule(int ruleIndex, EnforcerRuleDesc ruleDesc, EnforcerRuleHelper helper)
+            throws EnforcerRuleException {
+
+        if (getLog().isDebugEnabled()) {
+            getLog().debug(String.format("Executing Rule %d: %s", ruleIndex, ruleDesc.getRule()));
+        }
+
+        long startTime = System.currentTimeMillis();
+
+        try {
+            if (ruleDesc.getRule() instanceof EnforcerRule) {
+                executeRuleOld(ruleIndex, ruleDesc, helper);
+            } else if (ruleDesc.getRule() instanceof AbstractEnforcerRule) {
+                executeRuleNew(ruleIndex, ruleDesc);
+            }
+        } finally {
+            if (getLog().isDebugEnabled()) {
+                long workTime = System.currentTimeMillis() - startTime;
+                getLog().debug(String.format(
+                        "Finish Rule %d: %s take %d ms", ruleIndex, getRuleName(ruleDesc), workTime));
+            }
+        }
+    }
+
+    private void executeRuleOld(int ruleIndex, EnforcerRuleDesc ruleDesc, EnforcerRuleHelper helper)
+            throws EnforcerRuleException {
+
+        EnforcerRule rule = (EnforcerRule) ruleDesc.getRule();
+
+        if (ignoreCache || shouldExecute(rule)) {
+            rule.execute(helper);
+            getLog().info(String.format("Rule %d: %s executed", ruleIndex, getRuleName(ruleDesc)));
+        }
+    }
+
+    private void executeRuleNew(int ruleIndex, EnforcerRuleDesc ruleDesc) throws EnforcerRuleException {
+
+        AbstractEnforcerRule rule = (AbstractEnforcerRule) ruleDesc.getRule();
+        rule.setLog(rule.getLevel() == EnforcerLevel.ERROR ? enforcerLoggerError : enforcerLoggerWarn);
+
+        if (ignoreCache || !ruleCache.isCached(rule)) {
+            rule.execute();
+            getLog().info(String.format("Rule %d: %s executed", ruleIndex, getRuleName(ruleDesc)));
+        }
+    }
+
     /**
      * Create rules configuration based on command line provided rules list.
      *
@@ -316,7 +357,6 @@ public class EnforceMojo extends AbstractMojo {
      * Filter out (remove) rules that have been specifically skipped via additional configuration.
      *
      * @param allRules list of enforcer rules to go through and filter
-     *
      * @return list of filtered rules
      */
     private List<EnforcerRuleDesc> filterOutSkippedRules(List<EnforcerRuleDesc> allRules) {
@@ -379,18 +419,50 @@ public class EnforceMojo extends AbstractMojo {
         return failFast;
     }
 
-    protected String createRuleMessage(int i, String currentRule, EnforcerRuleException e) {
-        return "Rule " + i + ": " + currentRule + " failed with message:" + System.lineSeparator() + e.getMessage();
+    private String createRuleMessage(
+            int ruleIndex, EnforcerRuleDesc ruleDesc, EnforcerLevel level, EnforcerRuleException e) {
+
+        StringBuilder result = new StringBuilder();
+        result.append("Rule ").append(ruleIndex).append(": ").append(getRuleName(ruleDesc));
+
+        if (level == EnforcerLevel.ERROR) {
+            result.append(" failed");
+        } else {
+            result.append(" warned");
+        }
+
+        if (e.getMessage() != null) {
+            result.append(" with message:").append(System.lineSeparator()).append(e.getMessage());
+        } else {
+            result.append(" without a message");
+        }
+
+        return result.toString();
+    }
+
+    private String getRuleName(EnforcerRuleDesc ruleDesc) {
+
+        Class<? extends EnforcerRuleBase> ruleClass = ruleDesc.getRule().getClass();
+
+        String ruleName = ruleClass.getName();
+
+        if (!ruleClass.getSimpleName().equalsIgnoreCase(ruleDesc.getName())) {
+            ruleName += "(" + ruleDesc.getName() + ")";
+        }
+
+        return ruleName;
     }
 
     /**
      * Returns the level of the rule, defaults to {@link EnforcerLevel#ERROR} for backwards compatibility.
      *
-     * @param rule might be of type {@link EnforcerRule2}.
+     * @param rule might be of type {{@link AbstractEnforcerRule} or {@link EnforcerRule2}
      * @return level of the rule.
      */
-    private EnforcerLevel getLevel(EnforcerRule rule) {
-        if (rule instanceof EnforcerRule2) {
+    private EnforcerLevel getLevel(EnforcerRuleBase rule) {
+        if (rule instanceof AbstractEnforcerRule) {
+            return ((AbstractEnforcerRule) rule).getLevel();
+        } else if (rule instanceof EnforcerRule2) {
             return ((EnforcerRule2) rule).getLevel();
         } else {
             return EnforcerLevel.ERROR;
diff --git a/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/AbstarctEnforcerLogger.java b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/AbstarctEnforcerLogger.java
new file mode 100644
index 0000000..c3db464
--- /dev/null
+++ b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/AbstarctEnforcerLogger.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+package org.apache.maven.plugins.enforcer.internal;
+
+import java.util.Objects;
+import java.util.function.Supplier;
+
+import org.apache.maven.enforcer.rule.api.EnforcerLogger;
+import org.apache.maven.plugin.logging.Log;
+
+/**
+ * Base EnforcerLogger implementation
+ *
+ * @author Slawomir Jaranowski
+ * @since 3.2.0
+ */
+public abstract class AbstarctEnforcerLogger implements EnforcerLogger {
+
+    protected final Log log;
+
+    protected AbstarctEnforcerLogger(Log log) {
+        this.log = Objects.requireNonNull(log, "log must be not null");
+    }
+
+    @Override
+    public void debug(CharSequence message) {
+        log.debug(message);
+    }
+
+    @Override
+    public void debug(Supplier<CharSequence> messageSupplier) {
+        if (log.isDebugEnabled()) {
+            log.debug(messageSupplier.get());
+        }
+    }
+
+    @Override
+    public void info(CharSequence message) {
+        log.info(message);
+    }
+
+    @Override
+    public void info(Supplier<CharSequence> messageSupplier) {
+        if (log.isInfoEnabled()) {
+            log.info(messageSupplier.get());
+        }
+    }
+
+    @Override
+    public void warn(CharSequence message) {
+        log.warn(message);
+    }
+
+    @Override
+    public void warn(Supplier<CharSequence> messageSupplier) {
+        if (log.isWarnEnabled()) {
+            log.warn(messageSupplier.get());
+        }
+    }
+
+    @Override
+    public void error(CharSequence message) {
+        log.error(message);
+    }
+
+    @Override
+    public void error(Supplier<CharSequence> messageSupplier) {
+        if (log.isErrorEnabled()) {
+            log.error(messageSupplier.get());
+        }
+    }
+}
diff --git a/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestDefaultEnforcementRuleHelper.java b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerLoggerError.java
similarity index 55%
rename from maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestDefaultEnforcementRuleHelper.java
rename to maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerLoggerError.java
index a0ade16..ba6e6d6 100644
--- a/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestDefaultEnforcementRuleHelper.java
+++ b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerLoggerError.java
@@ -16,23 +16,33 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.plugins.enforcer.internal;
 
-import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
-import org.junit.jupiter.api.Test;
+import java.util.function.Supplier;
 
-import static org.junit.jupiter.api.Assertions.assertNotNull;
+import org.apache.maven.plugin.logging.Log;
 
 /**
- * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
+ * EnforcerLogger implementation for {@code ERROR} execution level
+ *
+ * @author Slawomir Jaranowski
+ * @since 3.2.0
  */
-public class TestDefaultEnforcementRuleHelper {
-    @Test
-    public void testHelper() throws ExpressionEvaluationException {
-        DefaultEnforcementRuleHelper helper = (DefaultEnforcementRuleHelper) EnforcerTestUtils.getHelper();
+public class EnforcerLoggerError extends AbstarctEnforcerLogger {
+
+    public EnforcerLoggerError(Log log) {
+        super(log);
+    }
+
+    @Override
+    public void warnOrError(CharSequence message) {
+        log.error(message);
+    }
 
-        assertNotNull(helper.getLog());
-        assertNotNull(helper.evaluate("${session}"));
-        assertNotNull(helper.evaluate("${project}"));
+    @Override
+    public void warnOrError(Supplier<CharSequence> messageSupplier) {
+        if (log.isErrorEnabled()) {
+            log.error(messageSupplier.get());
+        }
     }
 }
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerLoggerWarn.java
similarity index 57%
copy from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java
copy to maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerLoggerWarn.java
index e65464e..dbed991 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BannedDependencies.java
+++ b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerLoggerWarn.java
@@ -16,25 +16,33 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.plugins.enforcer.internal;
 
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugins.enforcer.utils.ArtifactUtils;
+import java.util.function.Supplier;
+
+import org.apache.maven.plugin.logging.Log;
 
 /**
- * This rule checks that lists of dependencies are not included.
+ * EnforcerLogger implementation for {@code WARN} execution level
  *
- * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
+ * @author Slawomir Jaranowski
+ * @since 3.2.0
  */
-public class BannedDependencies extends BannedDependenciesBase {
+public class EnforcerLoggerWarn extends AbstarctEnforcerLogger {
+
+    public EnforcerLoggerWarn(Log log) {
+        super(log);
+    }
+
     @Override
-    protected boolean validate(Artifact artifact) {
-        return !ArtifactUtils.matchDependencyArtifact(artifact, excludes)
-                || ArtifactUtils.matchDependencyArtifact(artifact, includes);
+    public void warnOrError(CharSequence message) {
+        log.warn(message);
     }
 
     @Override
-    protected String getErrorMessage() {
-        return "banned via the exclude/include list";
+    public void warnOrError(Supplier<CharSequence> messageSupplier) {
+        if (log.isWarnEnabled()) {
+            log.warn(messageSupplier.get());
+        }
     }
 }
diff --git a/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleCache.java b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleCache.java
new file mode 100644
index 0000000..14595de
--- /dev/null
+++ b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleCache.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+package org.apache.maven.plugins.enforcer.internal;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.maven.enforcer.rule.api.AbstractEnforcerRule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Service for manage rules cache storage.
+ *
+ * @author Slawomir Jaranowski
+ * @since 3.2.0
+ */
+@Named
+@Singleton
+public class EnforcerRuleCache {
+
+    private final Logger logger = LoggerFactory.getLogger(EnforcerRuleCache.class);
+
+    private final Map<Class<? extends AbstractEnforcerRule>, List<String>> cache = new HashMap<>();
+
+    public boolean isCached(AbstractEnforcerRule rule) {
+
+        String cacheId = rule.getCacheId();
+
+        if (cacheId == null) {
+            return false;
+        }
+
+        Class<? extends AbstractEnforcerRule> ruleClass = rule.getClass();
+        logger.debug("Check cache for {} with id {}", ruleClass, cacheId);
+
+        synchronized (this) {
+            List<String> cacheIdList = cache.computeIfAbsent(ruleClass, (k) -> new ArrayList<>());
+            if (cacheIdList.contains(cacheId)) {
+                logger.debug("Already cached {} with id {}", ruleClass, cacheId);
+                return true;
+            }
+            logger.debug("Add cache {} with id {}", ruleClass, cacheId);
+            cacheIdList.add(cacheId);
+        }
+
+        return false;
+    }
+}
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/EnforcerRuleDesc.java b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleDesc.java
similarity index 70%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/EnforcerRuleDesc.java
rename to maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleDesc.java
index 84d5977..ec0f8ed 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/EnforcerRuleDesc.java
+++ b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleDesc.java
@@ -16,24 +16,29 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.plugins.enforcer.internal;
 
-import org.apache.maven.enforcer.rule.api.EnforcerRule;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleBase;
 
 /**
- * Description of rule to eecute.
+ * Description of rule to execute.
+ *
+ * @author Slawomir Jaranowski
+ * @since 3.2.0
  */
 public class EnforcerRuleDesc {
 
     private final String name;
-    private final EnforcerRule rule;
+
+    private final EnforcerRuleBase rule;
 
     /**
      * Create a new Rule Description
+     *
      * @param name a rule name
      * @param rule a rule instance
      */
-    EnforcerRuleDesc(String name, EnforcerRule rule) {
+    public EnforcerRuleDesc(String name, EnforcerRuleBase rule) {
         this.name = name;
         this.rule = rule;
     }
@@ -42,7 +47,12 @@ public class EnforcerRuleDesc {
         return name;
     }
 
-    public EnforcerRule getRule() {
+    public EnforcerRuleBase getRule() {
         return rule;
     }
+
+    @Override
+    public String toString() {
+        return "EnforcerRuleDesc[name=" + name + ", rule=" + rule + "]";
+    }
 }
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/EnforcerRuleManager.java b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleManager.java
similarity index 62%
rename from enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/EnforcerRuleManager.java
rename to maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleManager.java
index 07531c9..0b2cd72 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/EnforcerRuleManager.java
+++ b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleManager.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.plugins.enforcer.internal;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -25,33 +25,52 @@ import javax.inject.Singleton;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
-import org.apache.maven.enforcer.rule.api.EnforcerRule;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleBase;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.MojoExecution;
 import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
+import org.apache.maven.plugins.enforcer.EnforcerRuleManagerException;
+import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.classworlds.realm.ClassRealm;
 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
 import org.codehaus.plexus.component.configurator.ComponentConfigurator;
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 import org.codehaus.plexus.configuration.PlexusConfiguration;
 
 /**
  * Manage enforcer rules.
+ *
+ * @author Slawomir Jaranowski
+ * @since 3.2.0
  */
 @Named
 @Singleton
 public class EnforcerRuleManager {
 
-    @Inject
-    private Provider<MavenSession> sessionProvider;
+    private final Provider<MavenSession> sessionProvider;
 
-    @Inject
-    private Provider<MojoExecution> mojoExecutionProvider;
+    private final Provider<MojoExecution> mojoExecutionProvider;
+
+    private final ComponentConfigurator componentConfigurator;
+
+    private final PlexusContainer plexusContainer;
 
     @Inject
-    @Named("basic")
-    private ComponentConfigurator componentConfigurator;
+    public EnforcerRuleManager(
+            Provider<MavenSession> sessionProvider,
+            Provider<MojoExecution> mojoExecutionProvider,
+            @Named("basic") ComponentConfigurator componentConfigurator,
+            PlexusContainer plexusContainer) {
+        this.sessionProvider = Objects.requireNonNull(sessionProvider, "sessionProvider must be not null");
+        this.mojoExecutionProvider =
+                Objects.requireNonNull(mojoExecutionProvider, "mojoExecutionProvider must be not null");
+        this.componentConfigurator =
+                Objects.requireNonNull(componentConfigurator, "componentConfigurator must be not null");
+        this.plexusContainer = Objects.requireNonNull(plexusContainer, "plexusContainer must be not null");
+    }
 
     /**
      * Create enforcer rules based on xml configuration.
@@ -93,6 +112,16 @@ public class EnforcerRuleManager {
 
     private EnforcerRuleDesc createRuleDesc(String name, String implementation) throws EnforcerRuleManagerException {
 
+        // component name should always start at lowercase character
+        String ruleName = Character.toLowerCase(name.charAt(0)) + name.substring(1);
+
+        try {
+            return new EnforcerRuleDesc(ruleName, plexusContainer.lookup(EnforcerRuleBase.class, ruleName));
+        } catch (ComponentLookupException e) {
+            // no component for rule
+            // process old way, by  class name
+        }
+
         String ruleClass;
         if (implementation != null && !implementation.isEmpty()) {
             ruleClass = implementation;
@@ -101,15 +130,16 @@ public class EnforcerRuleManager {
         }
 
         if (!ruleClass.contains(".")) {
-            ruleClass = getClass().getPackage().getName() + "." + Character.toUpperCase(ruleClass.charAt(0))
+            ruleClass = "org.apache.maven.plugins.enforcer." + Character.toUpperCase(ruleClass.charAt(0))
                     + ruleClass.substring(1);
         }
 
         try {
             return new EnforcerRuleDesc(
-                    name, (EnforcerRule) Class.forName(ruleClass).newInstance());
+                    name, (EnforcerRuleBase) Class.forName(ruleClass).newInstance());
         } catch (Exception e) {
-            throw new EnforcerRuleManagerException("Failed to create enforcer rules for class: " + ruleClass, e);
+            throw new EnforcerRuleManagerException(
+                    "Failed to create enforcer rules with name: " + ruleName + " or for class: " + ruleClass, e);
         }
     }
 }
diff --git a/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestEnforceMojo.java b/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestEnforceMojo.java
index cd25b7c..bead244 100644
--- a/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestEnforceMojo.java
+++ b/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestEnforceMojo.java
@@ -23,10 +23,15 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRule;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleError;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugins.enforcer.internal.EnforcerRuleDesc;
+import org.apache.maven.plugins.enforcer.internal.EnforcerRuleManager;
+import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.InjectMocks;
@@ -36,9 +41,13 @@ import org.mockito.junit.jupiter.MockitoExtension;
 import org.mockito.junit.jupiter.MockitoSettings;
 import org.mockito.quality.Strictness;
 
+import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 /**
@@ -53,22 +62,29 @@ class TestEnforceMojo {
     @Mock
     private EnforcerRuleManager ruleManager;
 
+    @Mock
+    private MavenSession session;
+
     @InjectMocks
     private EnforceMojo mojo;
 
     @Test
-    void testEnforceMojo() throws Exception {
-        setupBasics(false);
+    void emptyRuleListShouldThrowException() {
+        mojo.setFail(false);
 
-        Log logSpy = setupLogSpy();
+        assertThatCode(() -> mojo.execute())
+                .isInstanceOf(MojoExecutionException.class)
+                .hasMessage("No rules are configured. Use the skip flag if you want to disable execution.");
+    }
 
-        try {
-            mojo.execute();
-            fail("Expected a Mojo Execution Exception.");
-        } catch (MojoExecutionException e) {
-            System.out.println("Caught Expected Exception:" + e.getLocalizedMessage());
-        }
+    @Test
+    void failedRulesAndNoFailPassBuild() throws Exception {
+        // set fail to false
+        mojo.setFail(false);
+
+        Log logSpy = setupLogSpy();
 
+        // two rules which fail
         EnforcerRuleDesc[] rules = new EnforcerRuleDesc[2];
         rules[0] = new EnforcerRuleDesc("mockEnforcerRule", new MockEnforcerRule(true));
         rules[1] = new EnforcerRuleDesc("mockEnforcerRule", new MockEnforcerRule(true));
@@ -77,8 +93,51 @@ class TestEnforceMojo {
 
         mojo.execute();
 
-        Mockito.verify(logSpy, Mockito.times(2))
-                .info(Mockito.contains("Executing rule: " + MockEnforcerRule.class.getName()));
+        verify(logSpy)
+                .warn(Mockito.contains(
+                        "Rule 0: org.apache.maven.plugins.enforcer.MockEnforcerRule failed with message"));
+        verify(logSpy)
+                .warn(Mockito.contains(
+                        "Rule 1: org.apache.maven.plugins.enforcer.MockEnforcerRule failed with message"));
+    }
+
+    @Test
+    void breakBuildImmediately() throws Exception {
+        // set fail to false
+        mojo.setFail(false);
+
+        Log logSpy = setupLogSpy();
+
+        // this rule break build immediately
+        EnforcerRule ruleBreakBuild = Mockito.mock(EnforcerRule.class);
+        Mockito.doThrow(EnforcerRuleError.class).when(ruleBreakBuild).execute(any(EnforcerRuleHelper.class));
+
+        EnforcerRuleDesc[] rules = new EnforcerRuleDesc[3];
+        rules[0] = new EnforcerRuleDesc("mockEnforcerRule", new MockEnforcerRule(false));
+        rules[1] = new EnforcerRuleDesc("ruleBreakBuild", ruleBreakBuild);
+        rules[2] = new EnforcerRuleDesc("mockEnforcerRule", new MockEnforcerRule(false));
+
+        when(ruleManager.createRules(any())).thenReturn(Arrays.asList(rules));
+
+        Assertions.assertThatCode(() -> mojo.execute())
+                .isInstanceOf(MojoExecutionException.class)
+                .hasCauseInstanceOf(EnforcerRuleError.class);
+
+        assertTrue(((MockEnforcerRule) rules[0].getRule()).executed, "Expected this rule to be executed.");
+        assertFalse(((MockEnforcerRule) rules[2].getRule()).executed, "Expected this rule to be not executed.");
+
+        verify(logSpy).info(Mockito.contains("Rule 0: org.apache.maven.plugins.enforcer.MockEnforcerRule executed"));
+    }
+
+    @Test
+    void testEnforceMojo() throws Exception {
+        mojo.setFail(true);
+
+        EnforcerRuleDesc[] rules = new EnforcerRuleDesc[2];
+        rules[0] = new EnforcerRuleDesc("mockEnforcerRule", new MockEnforcerRule(true));
+        rules[1] = new EnforcerRuleDesc("mockEnforcerRule", new MockEnforcerRule(true));
+
+        when(ruleManager.createRules(any())).thenReturn(Arrays.asList(rules));
 
         try {
             mojo.setFailFast(false);
@@ -105,7 +164,7 @@ class TestEnforceMojo {
 
     @Test
     void testCaching() throws Exception {
-        setupBasics(true);
+        mojo.setFail(true);
 
         EnforcerRuleDesc[] rules = new EnforcerRuleDesc[10];
 
@@ -174,7 +233,7 @@ class TestEnforceMojo {
 
     @Test
     void testCachePersistence1() throws Exception {
-        setupBasics(true);
+        mojo.setFail(true);
 
         EnforcerRuleDesc[] rules = new EnforcerRuleDesc[10];
 
@@ -192,7 +251,7 @@ class TestEnforceMojo {
 
     @Test
     void testCachePersistence2() throws Exception {
-        setupBasics(true);
+        mojo.setFail(true);
 
         EnforcerRuleDesc[] rules = new EnforcerRuleDesc[10];
 
@@ -216,7 +275,7 @@ class TestEnforceMojo {
         } catch (InterruptedException e) {
         }
 
-        setupBasics(true);
+        mojo.setFail(true);
 
         EnforcerRuleDesc[] rules = new EnforcerRuleDesc[10];
 
@@ -234,7 +293,7 @@ class TestEnforceMojo {
     @Test
     void testLoggingOnEnforcerRuleExceptionWithMessage() throws Exception {
         // fail=false because this is out of scope here (also allows for cleaner test code without catch block)
-        setupBasics(false);
+        mojo.setFail(false);
 
         // the regular kind of EnforcerRuleException:
         EnforcerRuleException ruleException = new EnforcerRuleException("testMessage");
@@ -248,18 +307,16 @@ class TestEnforceMojo {
 
         mojo.execute();
 
-        Mockito.verify(logSpy).debug(Mockito.anyString(), Mockito.same(ruleException));
+        verify(logSpy, Mockito.never()).warn(Mockito.anyString(), any(Throwable.class));
 
-        Mockito.verify(logSpy, Mockito.never()).warn(Mockito.anyString(), any(Throwable.class));
-
-        Mockito.verify(logSpy)
+        verify(logSpy)
                 .warn(Mockito.matches(".* failed with message:" + System.lineSeparator() + ruleException.getMessage()));
     }
 
     @Test
     void testLoggingOnEnforcerRuleExceptionWithoutMessage() throws Exception {
         // fail=false because this is out of scope here (also allows for cleaner test code without catch block)
-        setupBasics(false);
+        mojo.setFail(false);
 
         // emulate behaviour of various rules that just catch Exception and wrap into EnforcerRuleException:
         NullPointerException npe = new NullPointerException();
@@ -275,27 +332,25 @@ class TestEnforceMojo {
 
         mojo.execute();
 
-        Mockito.verify(logSpy).warn(Mockito.contains("failed without a message"), Mockito.same(enforcerRuleException));
-
-        Mockito.verify(logSpy).warn(Mockito.matches(".* failed with message:" + System.lineSeparator() + "null"));
+        Mockito.verify(logSpy).warn(Mockito.matches(".* failed without a message"));
     }
 
     @Test
     void testFailIfNoTests() throws MojoExecutionException {
-        setupBasics(false);
+        mojo.setFail(false);
         mojo.setFailIfNoRules(false);
 
         Log logSpy = setupLogSpy();
 
         mojo.execute();
 
-        Mockito.verify(logSpy).warn("No rules are configured.");
+        verify(logSpy).warn("No rules are configured.");
         Mockito.verifyNoMoreInteractions(logSpy);
     }
 
     @Test
     void testFailIfBothRuleOverridePropertiesAreSet() throws MojoExecutionException {
-        setupBasics(false);
+        mojo.setFail(false);
 
         Log logSpy = setupLogSpy();
         List<String> rules = Arrays.asList("rule1", "rule2");
@@ -309,7 +364,7 @@ class TestEnforceMojo {
 
     @Test
     void testShouldPrintWarnWhenUsingDeprecatedRulesProperty() throws MojoExecutionException {
-        setupBasics(false);
+        mojo.setFail(false);
 
         Log logSpy = setupLogSpy();
 
@@ -321,7 +376,7 @@ class TestEnforceMojo {
 
     @Test
     void testShouldNotPrintWarnWhenDeprecatedRulesPropertyIsEmpty() throws MojoExecutionException {
-        setupBasics(false);
+        mojo.setFail(false);
 
         Log logSpy = setupLogSpy();
 
@@ -330,12 +385,6 @@ class TestEnforceMojo {
         Mockito.verifyNoInteractions(logSpy);
     }
 
-    private void setupBasics(boolean fail) {
-        mojo.setFail(fail);
-        mojo.setSession(EnforcerTestUtils.getMavenSession());
-        mojo.setProject(new MockProject());
-    }
-
     private Log setupLogSpy() {
         Log spy = Mockito.spy(mojo.getLog());
         mojo.setLog(spy);
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy b/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestRule1.java
similarity index 70%
copy from maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
copy to maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestRule1.java
index c05c677..fdef9a2 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
+++ b/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestRule1.java
@@ -16,8 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[WARNING] Rule 0: org.apache.maven.plugins.enforcer.AlwaysFail warned with message:' )
+package org.apache.maven.plugins.enforcer;
 
+import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
 
- 
\ No newline at end of file
+public class TestRule1 extends AbstractNonCacheableEnforcerRule {
+
+    @Override
+    public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException {}
+}
diff --git a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy b/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestRule2.java
similarity index 70%
copy from maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
copy to maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestRule2.java
index c05c677..4b2a2c5 100644
--- a/maven-enforcer-plugin/src/it/projects/always-fail-warn/verify.groovy
+++ b/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/TestRule2.java
@@ -16,8 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-File buildLog = new File( basedir, 'build.log' )
-assert buildLog.text.contains( '[WARNING] Rule 0: org.apache.maven.plugins.enforcer.AlwaysFail warned with message:' )
+package org.apache.maven.plugins.enforcer;
 
+import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
 
- 
\ No newline at end of file
+public class TestRule2 extends AbstractNonCacheableEnforcerRule {
+
+    @Override
+    public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException {}
+}
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerRuleManagerTest.java b/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleManagerTest.java
similarity index 66%
rename from enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerRuleManagerTest.java
rename to maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleManagerTest.java
index 99626cd..a068e50 100644
--- a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/EnforcerRuleManagerTest.java
+++ b/maven-enforcer-plugin/src/test/java/org/apache/maven/plugins/enforcer/internal/EnforcerRuleManagerTest.java
@@ -16,31 +16,39 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.plugins.enforcer;
+package org.apache.maven.plugins.enforcer.internal;
 
 import javax.inject.Provider;
 
 import java.util.List;
 
 import org.apache.maven.enforcer.rule.api.EnforcerRule;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleBase;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.MojoExecution;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugins.enforcer.EnforcerRuleManagerException;
+import org.apache.maven.plugins.enforcer.TestRule1;
+import org.apache.maven.plugins.enforcer.TestRule2;
+import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
 import org.codehaus.plexus.component.configurator.ComponentConfigurator;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 import org.codehaus.plexus.configuration.DefaultPlexusConfiguration;
 import org.codehaus.plexus.configuration.PlexusConfiguration;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.ArgumentCaptor;
-import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.junit.jupiter.MockitoExtension;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -58,10 +66,18 @@ class EnforcerRuleManagerTest {
     @Mock
     private ComponentConfigurator componentConfigurator;
 
-    @InjectMocks
+    @Mock
+    private PlexusContainer plexusContainer;
+
     private EnforcerRuleManager enforcerRuleManager;
 
-    void setupMocks() {
+    @BeforeEach
+    void setup() {
+        enforcerRuleManager =
+                new EnforcerRuleManager(sessionProvider, mojoExecutionProvider, componentConfigurator, plexusContainer);
+    }
+
+    void setupMocks() throws Exception {
         MojoExecution mojoExecution = mock(MojoExecution.class);
         when(mojoExecutionProvider.get()).thenReturn(mojoExecution);
 
@@ -71,10 +87,12 @@ class EnforcerRuleManagerTest {
         when(mojoDescriptor.getPluginDescriptor()).thenReturn(mock(PluginDescriptor.class));
 
         when(sessionProvider.get()).thenReturn(mock(MavenSession.class));
+
+        doThrow(ComponentLookupException.class).when(plexusContainer).lookup(any(Class.class), anyString());
     }
 
     @Test
-    void nulConfigReturnEmptyRules() throws Exception {
+    void nullConfigReturnEmptyRules() throws Exception {
 
         List<EnforcerRuleDesc> rules = enforcerRuleManager.createRules(null);
 
@@ -90,7 +108,7 @@ class EnforcerRuleManagerTest {
     }
 
     @Test
-    void unKnownRuleThrowException() {
+    void unKnownRuleThrowException() throws Exception {
 
         setupMocks();
 
@@ -98,17 +116,18 @@ class EnforcerRuleManagerTest {
 
         assertThatCode(() -> enforcerRuleManager.createRules(configuration))
                 .isInstanceOf(EnforcerRuleManagerException.class)
-                .hasMessage("Failed to create enforcer rules for class: org.apache.maven.plugins.enforcer.UnKnowRule")
+                .hasMessage(
+                        "Failed to create enforcer rules with name: unKnowRule or for class: org.apache.maven.plugins.enforcer.UnKnowRule")
                 .hasCauseInstanceOf(ClassNotFoundException.class);
     }
 
     @Test
-    void invalidConfigurationThrowException() throws ComponentConfigurationException {
+    void invalidConfigurationThrowException() throws Exception {
 
         setupMocks();
 
         PlexusConfiguration ruleConfig =
-                new DefaultPlexusConfiguration("alwaysPass").addChild("message", "messageValue");
+                new DefaultPlexusConfiguration("testRule1").addChild("message", "messageValue");
         PlexusConfiguration configuration = new DefaultPlexusConfiguration("rules");
         configuration.addChild(ruleConfig);
 
@@ -122,49 +141,70 @@ class EnforcerRuleManagerTest {
     }
 
     @Test
-    void createSimpleRule() throws EnforcerRuleManagerException {
+    void createSimpleRule() throws Exception {
+
+        setupMocks();
+
+        PlexusConfiguration configuration = new DefaultPlexusConfiguration("rules")
+                .addChild("TestRule1", null)
+                .addChild("testRule2", null);
+
+        List<EnforcerRuleDesc> rules = enforcerRuleManager.createRules(configuration);
+
+        assertThat(rules)
+                .hasSize(2)
+                .map(EnforcerRuleDesc::getRule)
+                .hasExactlyElementsOfTypes(TestRule1.class, TestRule2.class);
+
+        assertThat(rules).hasSize(2).map(EnforcerRuleDesc::getName).containsExactly("TestRule1", "testRule2");
+    }
+
+    @Test
+    void createSimpleRuleFromComponentAndClasses() throws Exception {
 
         setupMocks();
 
+        Mockito.doReturn(new TestRule1()).when(plexusContainer).lookup(EnforcerRuleBase.class, "testRule1");
+
         PlexusConfiguration configuration = new DefaultPlexusConfiguration("rules")
-                .addChild("AlwaysFail", null)
-                .addChild("alwaysPass", null);
+                .addChild("TestRule1", null)
+                .addChild("testRule2", null);
 
         List<EnforcerRuleDesc> rules = enforcerRuleManager.createRules(configuration);
 
         assertThat(rules)
                 .hasSize(2)
                 .map(EnforcerRuleDesc::getRule)
-                .hasExactlyElementsOfTypes(AlwaysFail.class, AlwaysPass.class);
+                .hasExactlyElementsOfTypes(TestRule1.class, TestRule2.class);
 
-        assertThat(rules).hasSize(2).map(EnforcerRuleDesc::getName).containsExactly("AlwaysFail", "alwaysPass");
+        assertThat(rules).hasSize(2).map(EnforcerRuleDesc::getName).containsExactly("testRule1", "testRule2");
     }
 
     @Test
-    void createRuleWithImplementation() throws EnforcerRuleManagerException {
+    void createRuleWithImplementation() throws Exception {
 
         setupMocks();
 
-        PlexusConfiguration ruleConfig = new DefaultPlexusConfiguration("alwaysPassWithImp");
-        ruleConfig.setAttribute("implementation", AlwaysPass.class.getName());
+        PlexusConfiguration ruleConfig = new DefaultPlexusConfiguration("testRuleWithImp");
+        ruleConfig.setAttribute("implementation", TestRule1.class.getName());
 
         PlexusConfiguration configuration = new DefaultPlexusConfiguration("rules");
         configuration.addChild(ruleConfig);
 
         List<EnforcerRuleDesc> rules = enforcerRuleManager.createRules(configuration);
 
-        assertThat(rules).hasSize(1).map(EnforcerRuleDesc::getRule).hasExactlyElementsOfTypes(AlwaysPass.class);
+        assertThat(rules).hasSize(1).map(EnforcerRuleDesc::getRule).hasExactlyElementsOfTypes(TestRule1.class);
 
-        assertThat(rules).hasSize(1).map(EnforcerRuleDesc::getName).containsExactly("alwaysPassWithImp");
+        assertThat(rules).hasSize(1).map(EnforcerRuleDesc::getName).containsExactly("testRuleWithImp");
     }
 
     @Test
-    void ruleShouldBeConfigured() throws EnforcerRuleManagerException, ComponentConfigurationException {
+    void ruleShouldBeConfigured() throws Exception {
 
         setupMocks();
 
         PlexusConfiguration ruleConfig =
-                new DefaultPlexusConfiguration("alwaysPass").addChild("message", "messageValue");
+                new DefaultPlexusConfiguration("testRule1").addChild("message", "messageValue");
         PlexusConfiguration configuration = new DefaultPlexusConfiguration("rules");
         configuration.addChild(ruleConfig);
 
@@ -177,7 +217,7 @@ class EnforcerRuleManagerTest {
         verify(componentConfigurator)
                 .configureComponent(ruleCaptor.capture(), configurationCaptor.capture(), any(), any());
 
-        assertThat(ruleCaptor.getValue()).isInstanceOf(AlwaysPass.class);
+        assertThat(ruleCaptor.getValue()).isInstanceOf(TestRule1.class);
         assertThat(configurationCaptor.getValue()).isSameAs(ruleConfig);
     }
 }