You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by rf...@apache.org on 2021/05/21 13:41:44 UTC

[maven-enforcer] 01/01: [MENFORCER-384] Introduce Maven Enforcer Extension

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

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

commit a6cf1a910997bb91fc0c6304387bcb3e2ea11598
Author: rfscholte <rf...@apache.org>
AuthorDate: Fri May 21 15:41:28 2021 +0200

    [MENFORCER-384] Introduce Maven Enforcer Extension
---
 maven-enforcer-extension/pom.xml                   | 124 +++++++++++++++
 maven-enforcer-extension/src/it/mrm/settings.xml   |  73 +++++++++
 .../projects/defaults/.mvn/enforcer-extension.xml  |  42 +++++
 .../src/it/projects/defaults/.mvn/extensions.xml   |  28 ++++
 .../src/it/projects/defaults/pom.xml               |  29 ++++
 .../src/it/projects/invoker.properties             |  19 +++
 .../extensions/enforcer/EnforceExtension.java      | 176 +++++++++++++++++++++
 maven-enforcer-extension/src/site/apt/index.apt    |  46 ++++++
 .../src/site/markdown/usage.md.vm                  |  54 +++++++
 maven-enforcer-extension/src/site/site.xml         |  34 ++++
 pom.xml                                            |   1 +
 11 files changed, 626 insertions(+)

diff --git a/maven-enforcer-extension/pom.xml b/maven-enforcer-extension/pom.xml
new file mode 100644
index 0000000..354fbed
--- /dev/null
+++ b/maven-enforcer-extension/pom.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  * Licensed to the Apache Software Foundation (ASF) under one
+  * or more contributor license agreements. See the NOTICE file
+  * distributed with this work for additional information
+  * regarding copyright ownership. The ASF licenses this file
+  * to you under the Apache License, Version 2.0 (the
+  * "License"); you may not use this file except in compliance
+  * with the License. You may obtain a copy of the License at
+  *
+  * http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing,
+  * software distributed under the License is distributed on an
+  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  * KIND, either express or implied. See the License for the
+  * specific language governing permissions and limitations
+  * under the License.
+  *
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.maven.enforcer</groupId>
+    <artifactId>enforcer</artifactId>
+    <version>3.0.0-M4-SNAPSHOT</version>
+  </parent>
+  <groupId>org.apache.maven.extensions</groupId>
+  <artifactId>maven-enforcer-extension</artifactId>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.eclipse.sisu</groupId>
+        <artifactId>sisu-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>index-project</id>
+            <goals>
+              <goal>main-index</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.plugin-tools</groupId>
+      <artifactId>maven-plugin-annotations</artifactId>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+  
+  <profiles>
+    <profile>
+      <id>run-its</id>
+      <properties>
+        <maven.it.failure.ignore>false</maven.it.failure.ignore>
+      </properties>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-invoker-plugin</artifactId>
+            <version>3.2.2</version>
+            <configuration>
+              <showErrors>true</showErrors>
+              <projectsDirectory>src/it/projects</projectsDirectory>
+              <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
+              <preBuildHookScript>setup</preBuildHookScript>
+              <postBuildHookScript>verify</postBuildHookScript>
+              <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
+              <settingsFile>src/it/mrm/settings.xml</settingsFile>
+              <ignoreFailures>${maven.it.failure.ignore}</ignoreFailures>
+              <goals>
+                <goal>validate</goal>
+              </goals>
+            </configuration>
+            <executions>
+              <execution>
+                <id>integration-test</id>
+                <goals>
+                  <goal>install</goal>
+                  <goal>run</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>mrm-maven-plugin</artifactId>
+            <version>1.2.0</version>
+            <executions>
+              <execution>
+                <goals>
+                  <goal>start</goal>
+                  <goal>stop</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <propertyName>repository.proxy.url</propertyName>
+              <repositories>
+                <mockRepo>
+                  <source>src/it/mrm/repository</source>
+                </mockRepo>
+                <proxyRepo />
+              </repositories>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>
\ No newline at end of file
diff --git a/maven-enforcer-extension/src/it/mrm/settings.xml b/maven-enforcer-extension/src/it/mrm/settings.xml
new file mode 100644
index 0000000..80734c5
--- /dev/null
+++ b/maven-enforcer-extension/src/it/mrm/settings.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  * Licensed to the Apache Software Foundation (ASF) under one
+  * or more contributor license agreements.  See the NOTICE file
+  * distributed with this work for additional information
+  * regarding copyright ownership.  The ASF licenses this file
+  * to you under the Apache License, Version 2.0 (the
+  * "License"); you may not use this file except in compliance
+  * with the License.  You may obtain a copy of the License at
+  *
+  * http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing,
+  * software distributed under the License is distributed on an
+  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  * KIND, either express or implied.  See the License for the
+  * specific language governing permissions and limitations
+  * under the License. 
+  *
+-->
+<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
+                      http://maven.apache.org/xsd/settings-1.0.0.xsd">
+  <mirrors>
+    <mirror>
+      <id>mrm-maven-plugin</id>
+      <name>Mock Repository Manager</name>
+      <url>@repository.proxy.url@</url>
+      <mirrorOf>*</mirrorOf>
+    </mirror>
+  </mirrors>
+  <profiles>
+    <profile>
+      <id>it-repo</id>
+      <repositories>
+        <repository>
+          <id>snapshots</id>
+          <url>@repository.proxy.url@</url>
+          <releases>
+            <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
+            <updatePolicy>never</updatePolicy>
+          </releases>
+          <snapshots>
+            <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
+            <updatePolicy>always</updatePolicy>
+          </snapshots>
+        </repository>
+      </repositories>
+      <pluginRepositories>
+        <pluginRepository>
+          <id>snapshots</id>
+          <url>@repository.proxy.url@</url>
+          <releases>
+            <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
+            <updatePolicy>never</updatePolicy>
+          </releases>
+          <snapshots>
+            <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
+            <updatePolicy>always</updatePolicy>
+          </snapshots>
+        </pluginRepository>
+      </pluginRepositories>
+    </profile>
+  </profiles>
+  <activeProfiles>
+    <activeProfile>it-repo</activeProfile>
+  </activeProfiles>
+</settings>
\ No newline at end of file
diff --git a/maven-enforcer-extension/src/it/projects/defaults/.mvn/enforcer-extension.xml b/maven-enforcer-extension/src/it/projects/defaults/.mvn/enforcer-extension.xml
new file mode 100644
index 0000000..8e86524
--- /dev/null
+++ b/maven-enforcer-extension/src/it/projects/defaults/.mvn/enforcer-extension.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<extension>
+  <executions>
+    <!-- defaults -->
+    <execution>
+      <configuration>
+        <rules>
+          <AlwaysPass />
+        </rules>
+      </configuration>
+    </execution>
+    <!-- configured -->
+    <execution>
+      <id>custom-id</id>
+      <phase>process-classes</phase>
+      <configuration>
+        <rules>
+          <AlwaysFail/>
+        </rules>
+      </configuration>
+    </execution>
+  </executions>
+</extension>
\ No newline at end of file
diff --git a/maven-enforcer-extension/src/it/projects/defaults/.mvn/extensions.xml b/maven-enforcer-extension/src/it/projects/defaults/.mvn/extensions.xml
new file mode 100644
index 0000000..da62f81
--- /dev/null
+++ b/maven-enforcer-extension/src/it/projects/defaults/.mvn/extensions.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  * Licensed to the Apache Software Foundation (ASF) under one
+  * or more contributor license agreements. See the NOTICE file
+  * distributed with this work for additional information
+  * regarding copyright ownership. The ASF licenses this file
+  * to you under the Apache License, Version 2.0 (the
+  * "License"); you may not use this file except in compliance
+  * with the License. You may obtain a copy of the License at
+  *
+  * http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing,
+  * software distributed under the License is distributed on an
+  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  * KIND, either express or implied. See the License for the
+  * specific language governing permissions and limitations
+  * under the License.
+  *
+-->
+<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
+  <extension>
+    <groupId>org.apache.maven.extensions</groupId>
+    <artifactId>maven-enforcer-extension</artifactId>
+    <version>@project.version@</version>
+  </extension>
+</extensions>
\ No newline at end of file
diff --git a/maven-enforcer-extension/src/it/projects/defaults/pom.xml b/maven-enforcer-extension/src/it/projects/defaults/pom.xml
new file mode 100644
index 0000000..2c4a137
--- /dev/null
+++ b/maven-enforcer-extension/src/it/projects/defaults/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<project>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.enforcer</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0</version>
+
+</project>
diff --git a/maven-enforcer-extension/src/it/projects/invoker.properties b/maven-enforcer-extension/src/it/projects/invoker.properties
new file mode 100644
index 0000000..9bbbd74
--- /dev/null
+++ b/maven-enforcer-extension/src/it/projects/invoker.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+invoker.goals.1 = validate
+invoker.goals.2 = verify
+invoker.buildResult.2 = failure
diff --git a/maven-enforcer-extension/src/main/java/org/apache/maven/extensions/enforcer/EnforceExtension.java b/maven-enforcer-extension/src/main/java/org/apache/maven/extensions/enforcer/EnforceExtension.java
new file mode 100644
index 0000000..b5aff43
--- /dev/null
+++ b/maven-enforcer-extension/src/main/java/org/apache/maven/extensions/enforcer/EnforceExtension.java
@@ -0,0 +1,176 @@
+package org.apache.maven.extensions.enforcer;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import javax.inject.Named;
+
+import org.apache.maven.AbstractMavenLifecycleParticipant;
+import org.apache.maven.MavenExecutionException;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Build;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginExecution;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+
+/**
+ * Extends every MavenProject with the maven-enforcer-plugin, adding executions as defined in 
+ * <code>.mvn/enforcer-extension.xml</code>
+ * 
+ * @since 3.0.0
+ */
+@Named( "enforcer" )
+public class EnforceExtension extends AbstractMavenLifecycleParticipant
+{
+    private static final String ENFORCER_EXTENSION_XML = ".mvn/enforcer-extension.xml";
+
+    private static final String POM_PROPERTIES =
+        "/META-INF/maven/org.apache.maven.extensions/maven-enforcer-extension/pom.properties";
+
+    @Override
+    public void afterProjectsRead( MavenSession session )
+        throws MavenExecutionException
+    {
+        Xpp3Dom configuration;
+        Path config = Paths.get( session.getExecutionRootDirectory(), ENFORCER_EXTENSION_XML );
+        if ( Files.isRegularFile( config ) )
+        {
+            try ( Reader reader = Files.newBufferedReader( config, StandardCharsets.UTF_8 ) )
+            {
+                configuration = Xpp3DomBuilder.build( reader );
+            }
+            catch ( XmlPullParserException | IOException e )
+            {
+                throw new MavenExecutionException( "Failed to read " + ENFORCER_EXTENSION_XML, e );
+            }
+        }
+        else
+        {
+            return;
+        }
+
+        List<PluginExecution> executions = null;
+        Xpp3Dom executionsDom = configuration.getChild( "executions" );
+        if ( executionsDom != null )
+        {
+            executions = new ArrayList<>();
+            for ( Xpp3Dom executionDom : executionsDom.getChildren( "execution" ) )
+            {
+                executions.add( getPluginExecution( executionDom ) );
+
+            }
+        }
+
+        if ( executions == null )
+        {
+            return;
+        }
+
+        for ( MavenProject project : session.getProjects() )
+        {
+            Plugin enforcerPlugin = null;
+            for ( Plugin plugin : project.getBuildPlugins() )
+            {
+                if ( "maven-enforcer-plugin".equals( plugin.getArtifactId() )
+                    && "org.apache.maven.plugins".equals( plugin.getGroupId() ) )
+                {
+                    enforcerPlugin = plugin;
+                }
+            }
+            
+            if ( enforcerPlugin == null )
+            {
+                enforcerPlugin = new Plugin();
+                enforcerPlugin.setGroupId( "org.apache.maven.plugins" );
+                enforcerPlugin.setArtifactId( "maven-enforcer-plugin" );
+
+                try ( InputStream is = EnforceExtension.class.getResourceAsStream( POM_PROPERTIES ) )
+                {
+                    Properties properties = new Properties();
+                    properties.load( is );
+                    enforcerPlugin.setVersion( properties.getProperty( "version" ) );
+                }
+                catch ( IOException e )
+                {
+                    // noop
+                }
+                
+                if ( project.getBuildPlugins().isEmpty() )
+                {
+                    Build build = project.getBuild();
+                    if ( build == null )
+                    {
+                        build = new Build();
+                        project.setBuild( build );
+                    }
+                    build.setPlugins( Collections.singletonList( enforcerPlugin ) );
+                }
+                else
+                {
+                    List<Plugin> buildPlugins = new ArrayList<>( project.getBuildPlugins() );
+                    buildPlugins.add( enforcerPlugin );
+                    project.getBuild().setPlugins( buildPlugins );
+                }
+            }
+
+            for ( PluginExecution pe : executions )
+            {
+                enforcerPlugin.addExecution( pe );
+            }
+        }
+    }
+
+    private static PluginExecution getPluginExecution( Xpp3Dom execution )
+    {
+        PluginExecution pluginExecution = new PluginExecution();
+        pluginExecution.setId( get( execution, "id", "default-extension" ) );
+        pluginExecution.addGoal( "enforce" );
+        pluginExecution.setPhase( get( execution, "phase", "validate" ) );
+        // here we must use Mavens internal configuration implementation
+        pluginExecution.setConfiguration( execution.getChild( "configuration" ) );
+        return pluginExecution;
+    }
+
+    private static String get( Xpp3Dom elm, String name, String defaultValue )
+    {
+        if ( elm == null || elm.getChild( name ) == null )
+        {
+            return defaultValue;
+        }
+        else
+        {
+            return elm.getChild( name ).getValue();
+        }
+    }
+}
diff --git a/maven-enforcer-extension/src/site/apt/index.apt b/maven-enforcer-extension/src/site/apt/index.apt
new file mode 100644
index 0000000..1d00ac3
--- /dev/null
+++ b/maven-enforcer-extension/src/site/apt/index.apt
@@ -0,0 +1,46 @@
+~~ 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.
+
+  ------
+  Introduction
+  ------
+  Robert Scholte
+  ------
+  May 2021
+  ------
+
+Maven Enforcer Extension - The Extended Loving Iron Fist of Maven\x99
+
+  The Enforcer Extension provides a way to globally define rules without making use of pom inheritence.
+  This way you don't have to adjust the pom.xml , but you can enforce a set of rules.   
+  
+* Usage
+
+  General instructions on how to use the Enforcer Plugin can be found on the {{{./usage.html}usage page}}.
+  
+  In case you still have questions regarding the plugin's usage, please have a look at the {{{./faq.html}FAQ}} and feel
+  free to contact the {{{./mailing-lists.html}user mailing list}}. The posts to the mailing list are archived and could
+  already contain the answer to your question as part of an older thread. Hence, it is also worth browsing/searching
+  the {{{./mailing-lists.html}mail archive}}.
+
+  If you feel like the plugin is missing a feature or has a defect, you can fill a feature request or bug report in our
+  {{{./issue-management.html}issue tracker}}. When creating a new issue, please provide a comprehensive description of your
+  concern. Especially for fixing bugs it is crucial that the developers can reproduce your problem. For this reason,
+  entire debug logs, POMs or most preferably little demo projects attached to the issue are very much appreciated.
+  Of course, patches are welcome, too. Contributors can check out the project from our
+  {{{./scm.html}source repository}} and will find supplementary information in the
+  {{{/guides/development/guide-helping.html}guide to helping with Maven}}.
diff --git a/maven-enforcer-extension/src/site/markdown/usage.md.vm b/maven-enforcer-extension/src/site/markdown/usage.md.vm
new file mode 100644
index 0000000..a9a4ec9
--- /dev/null
+++ b/maven-enforcer-extension/src/site/markdown/usage.md.vm
@@ -0,0 +1,54 @@
+<!--
+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.
+-->
+
+Usage
+=====
+
+To use the maven-enforcer-extension, you must register the extension and configuration.
+
+Maven Extension
+---------------
+
+You have 2 ways to use Maven extensions within your builds:
+
+* add `maven-enforcer-extension-${project.version}.jar` in `${maven.home}/lib/ext` (no extra dependencies required),
+
+* (since Maven 3.3.1) configure your extension in [.mvn/extensions.xml](https://maven.apache.org/ref/current/maven-embedder/core-extensions.html).
+
+There is actually a third way: add the extension to the `pom.xml`, but in that case it makes more sense to use the [maven-enforcer-plugin](../maven-enforcer-plugin/) instead.
+
+Enforcer Extension
+------------------
+
+The `.mvn/enforcer-extension.xml` in the root of your Maven project is where you define your rules.
+It's content is similar to an execution-block of the maven-enforcer-plugin
+
+```xml
+<extension>
+  <executions>
+    <execution>
+      <id/> <!-- default: default-extension -->
+      <phase/> <!-- default: validate -->
+      <configuration> <!-- see Plugin Configuration -->
+        <rules/>
+      </configuration>
+    </execution>
+  </executions>
+</extension>
+```
diff --git a/maven-enforcer-extension/src/site/site.xml b/maven-enforcer-extension/src/site/site.xml
new file mode 100644
index 0000000..3929b21
--- /dev/null
+++ b/maven-enforcer-extension/src/site/site.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<project xmlns="http://maven.apache.org/DECORATION/1.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/DECORATION/1.0.0 http://maven.apache.org/xsd/decoration-1.0.0.xsd"
+  name="Maven Enforcer plugin">
+  <body>
+    <menu name="Overview">
+      <item name="Introduction" href="index.html"/>
+      <item name="Usage" href="usage.html"/>
+      <!-- According to https://issues.apache.org/jira/browse/MNGSITE-152 -->
+      <item name="License" href="http://www.apache.org/licenses/"/>
+      <item name="Download" href="../download.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/pom.xml b/pom.xml
index 6902e5c..d98ac64 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,7 @@
     <module>enforcer-api</module>
     <module>enforcer-rules</module>
     <module>maven-enforcer-plugin</module>
+    <module>maven-enforcer-extension</module>
   </modules>
 
   <scm>