[maven-release-plugin]  copy for tag enforcer-1.2

git-svn-id: https://svn.apache.org/repos/asf/maven/enforcer/tags/enforcer-1.2@1414931 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d9e3259
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+target
+.idea/
+*.iml
diff --git a/enforcer-api/pom.xml b/enforcer-api/pom.xml
index 19b66d1..43966e4 100644
--- a/enforcer-api/pom.xml
+++ b/enforcer-api/pom.xml
@@ -28,7 +28,6 @@
   </parent>
 
   <artifactId>enforcer-api</artifactId>
-  <version>1.2</version>
   <packaging>jar</packaging>
 
   <name>Enforcer API</name>
@@ -58,17 +57,6 @@
         </configuration>
       </plugin>
       <plugin>
-        <groupId>org.codehaus.plexus</groupId>
-        <artifactId>plexus-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <goals>
-              <goal>descriptor</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-assembly-plugin</artifactId>
         <version>2.2-beta-2</version>
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 b168793..feeb30a 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
@@ -220,7 +220,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-enforcer-plugin</artifactId>
-        <version>1.0-beta-1</version>
+        <version>${project.version}</version>
         <dependencies>
           <dependency>
             <groupId>custom-rule</groupId>
@@ -261,7 +261,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-enforcer-plugin</artifactId>
-        <version>1.0-beta-1</version>
+        <version>${project.version}</version>
         <dependencies>
           <dependency>
             <groupId>custom-rule</groupId>
diff --git a/enforcer-rules/pom.xml b/enforcer-rules/pom.xml
index 3a980ee..2ced778 100644
--- a/enforcer-rules/pom.xml
+++ b/enforcer-rules/pom.xml
@@ -28,7 +28,6 @@
   </parent>
 
   <artifactId>enforcer-rules</artifactId>
-  <version>1.2</version>
   <packaging>jar</packaging>
 
   <name>Enforcer Rules</name>
@@ -88,7 +87,7 @@
     <dependency>
       <groupId>org.apache.maven.shared</groupId>
       <artifactId>maven-dependency-tree</artifactId>
-      <version>1.2</version>
+      <version>2.0</version>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
@@ -100,17 +99,6 @@
   <build>
     <plugins>
       <plugin>
-        <groupId>org.codehaus.plexus</groupId>
-        <artifactId>plexus-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <goals>
-              <goal>descriptor</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
         <executions>
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractPropertyEnforcerRule.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractPropertyEnforcerRule.java
new file mode 100755
index 0000000..1094221
--- /dev/null
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/AbstractPropertyEnforcerRule.java
@@ -0,0 +1,102 @@
+package org.apache.maven.plugins.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 org.apache.maven.enforcer.rule.api.EnforcerRuleException;

+import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;

+

+/**

+ * Abstract enforcer rule that give a foundation to validate properties from multiple sources.

+ *

+ * @author Paul Gier

+ * @author <a href='mailto:marvin[at]marvinformatics[dot]com'>Marvin Froeder</a>

+ * @version $Id: AbstractPropertyEnforcerRule.java $

+ */

+public abstract class AbstractPropertyEnforcerRule

+    extends AbstractNonCacheableEnforcerRule

+{

+

+    /**

+     * Match the property value to a given regular expression. Defaults to <code>null</code> (any value is ok).

+     */

+    public String regex = null;

+

+    /**

+     * Specify a warning message if the regular expression is not matched.

+     */

+    public String regexMessage = null;

+

+    public AbstractPropertyEnforcerRule()

+    {

+        super();

+    }

+

+    /**

+     * Execute the rule.

+     *

+     * @param helper the helper

+     * @throws EnforcerRuleException the enforcer rule exception

+     */

+    public void execute( EnforcerRuleHelper helper )

+        throws EnforcerRuleException

+    {

+        Object propValue = resolveValue( helper );

+

+        // Check that the property is not null or empty string

+        if ( propValue == null )

+        {

+            if ( message == null )

+            {

+                message = getName() + " \"" + getPropertyName() + "\" is required for this build.";

+            }

+            throw new EnforcerRuleException( message );

+        }

+        // If there is a regex, check that the property matches it

+        if ( regex != null && !propValue.toString().matches( regex ) )

+        {

+            if ( regexMessage == null )

+            {

+                regexMessage = getName() + " \"" + getPropertyName() + "\" evaluates to \"" + propValue + "\".  "

+                    + "This does not match the regular expression \"" + regex + "\"";

+            }

+            throw new EnforcerRuleException( regexMessage );

+        }

+    }

+

+    /**

+     * How the property that is being evaluated is called

+     */

+    public abstract String getName();

+

+    /**

+     * The name of the property currently being evaluated, this is used for default message pourpouses only

+     */

+    public abstract String getPropertyName();

+

+    /**

+     * Resolves the property value

+     *

+     * @param helper

+     * @throws EnforcerRuleException

+     */

+    public abstract Object resolveValue( EnforcerRuleHelper helper )

+        throws EnforcerRuleException;

+

+}
\ No newline at end of file
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
new file mode 100644
index 0000000..58f6b86
--- /dev/null
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/BanTransitiveDependencies.java
@@ -0,0 +1,199 @@
+package org.apache.maven.plugins.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.util.Collections;
+import java.util.List;
+
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+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.plugins.enforcer.utils.ArtifactMatcher;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
+import org.apache.maven.shared.dependency.graph.DependencyNode;
+import org.apache.maven.shared.dependency.graph.internal.DefaultDependencyGraphBuilder;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.logging.console.ConsoleLogger;
+
+/**
+ * This rule bans all transitive dependencies. There is a configuration option to exclude certain artifacts from being
+ * checked.
+ * 
+ * @author Jakub Senko
+ */
+public class BanTransitiveDependencies
+    extends AbstractNonCacheableEnforcerRule
+    implements EnforcerRule
+{
+
+    private EnforcerRuleHelper helper;
+
+    /**
+     * Specify the dependencies that will be ignored. This can be a list of artifacts in the format
+     * <code>groupId[:artifactId][:version][:type][:scope]</code>. Wildcard '*' can be used to in place of specific
+     * section (ie group:*:1.0 will match both 'group:artifact:1.0' and 'group:anotherArtifact:1.0') <br>
+     * You can override this patterns by using includes. Version is a string representing standard maven version range.
+     * Empty patterns will be ignored.
+     */
+    private List<String> excludes;
+
+    /**
+     * Specify the dependencies that will be checked. These are exceptions to excludes intended for more convenient and
+     * finer settings. This can be a list of artifacts in the format
+     * <code>groupId[:artifactId][:version][:type][:scope]</code>. Wildcard '*' can be used to in place of specific
+     * section (ie group:*:1.0 will match both 'group:artifact:1.0' and 'group:anotherArtifact:1.0') <br>
+     * Version is a string representing standard maven version range. Empty patterns will be ignored.
+     */
+    private List<String> includes;
+
+    /**
+     * Searches dependency tree recursively for transitive dependencies that are not excluded, while generating nice
+     * info message along the way.
+     * 
+     * @throws InvalidVersionSpecificationException
+     */
+    private static boolean searchTree( DependencyNode node, int level, ArtifactMatcher excludes, StringBuilder message )
+        throws InvalidVersionSpecificationException
+    {
+
+        List<DependencyNode> children = node.getChildren();
+
+        /*
+         * if the node is deeper than direct dependency and is empty, it is transitive.
+         */
+        boolean hasTransitiveDependencies = level > 1;
+
+        boolean excluded = false;
+
+        /*
+         * holds recursive message from children, will be appended to current message if this node has any transitive
+         * descendants if message is null, don't generate recursive message.
+         */
+        StringBuilder messageFromChildren = message == null ? null : new StringBuilder();
+
+        if ( excludes.match( node.getArtifact() ) )
+        {
+            // is excluded, we don't care about descendants
+            excluded = true;
+            hasTransitiveDependencies = false;
+        }
+        else
+        {
+            for ( DependencyNode childNode : children )
+            {
+                /*
+                 * if any of the children has transitive d. so does the parent
+                 */
+                hasTransitiveDependencies =
+                    ( searchTree( childNode, level + 1, excludes, messageFromChildren ) || hasTransitiveDependencies );
+            }
+        }
+
+        if ( ( excluded || hasTransitiveDependencies ) && message != null ) // then generate message
+        {
+            for ( int i = 0; i < level; i++ )
+            {
+                message.append( "   " );
+            }
+
+            message.append( node.getArtifact() );
+
+            if ( excluded )
+            {
+                message.append( " [excluded]\n" );
+            }
+
+            if ( hasTransitiveDependencies )
+            {
+                if ( level == 1 )
+                {
+                    message.append( " has transitive dependencies:" );
+                }
+
+                message.append( "\n" ).append( messageFromChildren );
+            }
+        }
+
+        return hasTransitiveDependencies;
+    }
+
+    public void execute( EnforcerRuleHelper helper )
+        throws EnforcerRuleException
+    {
+        this.helper = helper;
+
+        if ( excludes == null )
+        {
+            excludes = Collections.emptyList();
+        }
+        if ( includes == null )
+        {
+            includes = Collections.emptyList();
+        }
+
+        final ArtifactMatcher exclusions = new ArtifactMatcher( excludes, includes );
+
+        DependencyNode rootNode = null;
+
+        try
+        {
+            MavenProject project = (MavenProject) helper.evaluate( "${project}" );
+            rootNode = createDependencyGraphBuilder().buildDependencyGraph( project, null );
+        }
+        catch ( Exception e )
+        {
+            throw new EnforcerRuleException( "Error: Could not construct dependency tree.", e );
+        }
+
+        StringBuilder generatedMessage = null;
+        if ( message == null )
+        {
+            generatedMessage = new StringBuilder();
+        }
+
+        try
+        {
+            if ( searchTree( rootNode, 0, exclusions, generatedMessage ) )
+            {
+                throw new EnforcerRuleException( message == null ? generatedMessage.toString() : message );
+            }
+        }
+        catch ( InvalidVersionSpecificationException e )
+        {
+            throw new EnforcerRuleException( "Error: Invalid version range.", e );
+        }
+
+    }
+
+    private DependencyGraphBuilder createDependencyGraphBuilder()
+        throws ComponentLookupException
+    {
+        DefaultDependencyGraphBuilder builder =
+            (DefaultDependencyGraphBuilder) helper.getContainer().lookup( DependencyGraphBuilder.class.getCanonicalName(),
+                                                                          "default" );
+
+        builder.enableLogging( new ConsoleLogger( ConsoleLogger.LEVEL_DISABLED, "DefaultDependencyGraphBuilder" ) );
+
+        return builder;
+    }
+
+}
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 bb7409a..753614d 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
@@ -123,7 +123,7 @@
             errorMsgs.addAll( getConvergenceErrorMsgs( visitor.getConflictedVersionNumbers() ) );
             for ( CharSequence errorMsg : errorMsgs )
             {
-                log.error( errorMsg );
+                log.warn( errorMsg );
             }
             if ( errorMsgs.size() > 0 )
             {
diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireEnvironmentVariable.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireEnvironmentVariable.java
new file mode 100755
index 0000000..f79f964
--- /dev/null
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireEnvironmentVariable.java
@@ -0,0 +1,75 @@
+package org.apache.maven.plugins.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 org.apache.maven.enforcer.rule.api.EnforcerRule;

+import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;

+

+/**

+ * This rule checks that certain environment variable is set.

+ *

+ * @author <a href='mailto:marvin[at]marvinformatics[dot]com'>Marvin Froeder</a>

+ */

+public class RequireEnvironmentVariable

+    extends AbstractPropertyEnforcerRule

+{

+

+    /**

+     * Specify the required variable.

+     */

+    public String variableName = null;

+

+    @Override

+    public String resolveValue( EnforcerRuleHelper helper )

+    {

+        String envValue = System.getenv( variableName );

+        return envValue;

+    }

+

+    public boolean isCacheable()

+    {

+        // environment variables won't change while maven is on the run

+        return true;

+    }

+

+    public boolean isResultValid( EnforcerRule cachedRule )

+    {

+        // this rule shall always have the same result, since environment

+        // variables are set before maven is launched

+        return true;

+    }

+

+    public String getCacheId()

+    {

+        return variableName;

+    }

+

+    @Override

+    public String getPropertyName()

+    {

+        return variableName;

+    }

+

+    @Override

+    public String getName()

+    {

+        return "Environment variable";

+    }

+}

diff --git a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireProperty.java b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireProperty.java
index fec2a23..d2852e0 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireProperty.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/RequireProperty.java
@@ -25,29 +25,18 @@
 
 /**
  * This rule checks that certain properties are set.
- *
+ * 
  * @author Paul Gier
  */
 public class RequireProperty
-    extends AbstractNonCacheableEnforcerRule
+    extends AbstractPropertyEnforcerRule
 {
 
     /** Specify the required property. */
     public String property = null;
 
-    /** Match the property value to a given regular expression. Defaults to <code>null</code> (any value is ok). */
-    public String regex = null;
-
-    /** Specify a warning message if the regular expression is not matched. */
-    public String regexMessage = null;
-
-    /**
-     * Execute the rule.
-     *
-     * @param helper the helper
-     * @throws EnforcerRuleException the enforcer rule exception
-     */
-    public void execute( EnforcerRuleHelper helper )
+    @Override
+    public Object resolveValue( EnforcerRuleHelper helper )
         throws EnforcerRuleException
     {
         Object propValue = null;
@@ -59,26 +48,23 @@
         {
             throw new EnforcerRuleException( "Unable to evaluate property: " + property, eee );
         }
+        return propValue;
+    }
 
-        // Check that the property is not null or empty string
-        if ( propValue == null )
-        {
-            if ( message == null )
-            {
-                message = "Property \"" + property + "\" is required for this build.";
-            }
-            throw new EnforcerRuleException( message );
-        }
-        // If there is a regex, check that the property matches it
-        if ( regex != null && !propValue.toString().matches( regex ) )
-        {
-            if ( regexMessage == null )
-            {
-                regexMessage =
-                    "Property \"" + property + "\" evaluates to \"" + propValue + "\".  " +
-                        "This does not match the regular expression \"" + regex + "\"";
-            }
-            throw new EnforcerRuleException( regexMessage );
-        }
+    protected String resolveValue()
+    {
+        return null;
+    }
+
+    @Override
+    public String getPropertyName()
+    {
+        return property;
+    }
+
+    @Override
+    public String getName()
+    {
+        return "Property";
     }
 }
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/plugins/enforcer/utils/ArtifactMatcher.java
new file mode 100644
index 0000000..77d5b03
--- /dev/null
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactMatcher.java
@@ -0,0 +1,183 @@
+package org.apache.maven.plugins.enforcer.utils;
+
+/*
+ * 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.util.Collection;
+import java.util.LinkedList;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.plugins.enforcer.AbstractVersionEnforcer;
+import org.apache.maven.plugins.enforcer.BanTransitiveDependencies;
+
+/**
+ * This class is used for matching Artifacts against a list of patterns.
+ * 
+ * @author Jakub Senko
+ * @see BanTransitiveDependencies
+ */
+public final class ArtifactMatcher
+{
+
+    public static class Pattern
+    {
+        private String pattern;
+
+        private String[] parts;
+
+        public Pattern( String pattern )
+        {
+            if ( pattern == null )
+                throw new NullPointerException( "pattern" );
+
+            this.pattern = pattern;
+
+            parts = pattern.split( ":", 6 );
+
+            if ( parts.length == 6 )
+                throw new IllegalArgumentException( "Pattern contains too many delimiters." );
+
+            for ( String part : parts )
+            {
+                if ( "".equals( part ) )
+                    throw new IllegalArgumentException( "Pattern or its part is empty." );
+            }
+        }
+
+        public boolean match( Artifact artifact )
+            throws InvalidVersionSpecificationException
+        {
+            if ( artifact == null )
+                throw new NullPointerException( "artifact" );
+
+            switch ( parts.length )
+            {
+                case 5:
+                    String scope = artifact.getScope();
+                    if ( scope == null || scope.equals( "" ) )
+                    {
+                        scope = "compile";
+                    }
+
+                    if ( !"*".equals( parts[4] ) && !parts[4].equals( scope ) )
+                        return false;
+
+                case 4:
+                    String type = artifact.getType();
+                    if ( type == null || type.equals( "" ) )
+                    {
+                        type = "jar";
+                    }
+
+                    if ( !"*".equals( parts[3] ) && !parts[3].equals( type ) )
+                        return false;
+
+                case 3:
+                    if ( !"*".equals( parts[2] ) && !parts[2].equals( artifact.getVersion() ) )
+                    {
+                        if ( !AbstractVersionEnforcer.containsVersion( VersionRange.createFromVersionSpec( parts[2] ),
+                                                                       new DefaultArtifactVersion(
+                                                                                                   artifact.getVersion() ) ) )
+                        {
+                            return false;
+                        }
+                    }
+
+                case 2:
+                    if ( !"*".equals( parts[1] ) && !parts[1].equals( artifact.getArtifactId() ) )
+                        return false;
+
+                case 1:
+                    if ( !"*".equals( parts[0] ) && !parts[0].equals( artifact.getGroupId() ) )
+                        return false;
+                    else
+                        return true;
+                default:
+                    throw new AssertionError();
+            }
+        }
+
+        @Override
+        public String toString()
+        {
+            return pattern;
+        }
+    }
+
+    private Collection<Pattern> patterns = new LinkedList<Pattern>();
+
+    private Collection<Pattern> ignorePatterns = new LinkedList<Pattern>();
+
+    /**
+     * Construct class by providing patterns as strings. Empty strings are ignored.
+     * 
+     * @throws NullPointerException if any of the arguments is null
+     */
+    public ArtifactMatcher( final Collection<String> patterns, final Collection<String> ignorePatterns )
+    {
+        if ( patterns == null )
+            throw new NullPointerException( "patterns" );
+        if ( ignorePatterns == null )
+            throw new NullPointerException( "ignorePatterns" );
+
+        for ( String pattern : patterns )
+        {
+            if ( pattern != null && !"".equals( pattern ) )
+            {
+                this.patterns.add( new Pattern( pattern ) );
+            }
+        }
+
+        for ( String ignorePattern : ignorePatterns )
+        {
+            if ( ignorePattern != null && !"".equals( ignorePattern ) )
+            {
+                this.ignorePatterns.add( new Pattern( ignorePattern ) );
+            }
+        }
+    }
+
+    /**
+     * Check if artifact matches patterns.
+     * 
+     * @throws InvalidVersionSpecificationException
+     */
+    public boolean match( Artifact artifact )
+        throws InvalidVersionSpecificationException
+    {
+        for ( Pattern pattern : patterns )
+        {
+            if ( pattern.match( artifact ) )
+            {
+                for ( Pattern ignorePattern : ignorePatterns )
+                {
+                    if ( ignorePattern.match( artifact ) )
+                        return false;
+                }
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
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/plugins/enforcer/utils/DependencyVersionMap.java
index 44d0338..b4b423d 100644
--- a/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DependencyVersionMap.java
+++ b/enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/DependencyVersionMap.java
@@ -84,8 +84,7 @@
     
     private String getVersion( Artifact artifact )
     {
-        log.info( ArtifactUtils.versionlessKey( artifact ) + " " + artifact.getVersion() + " " + artifact.getBaseVersion() );
-        return uniqueVersions ? artifact.getVersion() : artifact.getBaseVersion(); 
+        return uniqueVersions ? artifact.getVersion() : artifact.getBaseVersion();
     }
 
     private boolean containsConflicts( DependencyNode node )
diff --git a/enforcer-rules/src/site/apt/banTransitiveDependencies.apt.vm b/enforcer-rules/src/site/apt/banTransitiveDependencies.apt.vm
new file mode 100644
index 0000000..efdaced
--- /dev/null
+++ b/enforcer-rules/src/site/apt/banTransitiveDependencies.apt.vm
@@ -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.    
+ 
+  ------
+  Ban Transitive Dependencies
+  ------
+  ------
+  August 2012
+  ------
+
+Ban Transitive Dependencies
+
+  This rule bans all transitive dependencies.
+
+
+   The following parameters are supported by this rule:
+   
+   * excludes - specify the dependencies that will be ignored.\
+      This can be a list of artifacts in the format
+      groupId[:artifactId[:version[:type[:scope]]]] .
+      Wildcard '*' can be used to in place of specific section (e.g. group:*:1.0 will match both 'group:artifact:1.0' and 'group:anotherArtifact:1.0')
+      Version is a string representing standard maven version range. Empty patterns will be ignored. 
+
+   * includes - specify the dependencies that will be checked.\
+     These are exceptions to excludes intended for more convenient configuration. This can be a list of artifacts in the format
+     groupId[:artifactId[:version[:type[:scope]]]] as above.
+ 
+   * message - an optional message to the user if the rule fails. Will replace generated report message.
+   
+   []
+
+   
+  Sample Plugin Configuration:
+  
++---+
+<project>
+  [...]
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>${project.version}</version>
+        <executions>
+          <execution>
+            <id>enforce-banned-dependencies</id>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <banTransitiveDependencies>
+                  <excludes>
+                    <!-- the rule will not fail even if it detects ignoredArtifact
+                         of group org.apache.maven, because it is excluded -->
+                    <exclude>org.apache.maven:ignoredArtifact</exclude>
+                    <exclude>*:anotherIgnoredArtifact</exclude>
+                  </excludes>
+                  <includes>
+                    <!-- override "org.apache.maven:ignoredArtifact" to fail
+                         if exactly 1.0 version of ignoreArtifact is detected
+                         to be transitive dependency of the project -->
+                    <include>org.apache.maven:ignoredArtifact:[1.0]</include>
+                  </includes>
+                </banTransitiveDependencies>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  [...]
+</project>
++---+
\ No newline at end of file
diff --git a/enforcer-rules/src/site/apt/bannedPlugins.apt.vm b/enforcer-rules/src/site/apt/bannedPlugins.apt.vm
new file mode 100644
index 0000000..8c91ca6
--- /dev/null
+++ b/enforcer-rules/src/site/apt/bannedPlugins.apt.vm
@@ -0,0 +1,87 @@
+~~ 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.    
+ 
+  ------
+  Banned Plugins
+  ------
+  Paul Gier
+  ------
+  November 2012
+  ------
+
+Banned Plugins
+
+   This rule checks the set of plugins used during the build and enforces that specific excluded plugins are not used.
+
+   The following parameters are supported by this rule:
+   
+   * excludes - a list of plugin artifacts to ban. The format is groupId[:artifactId][:version] where artifactId and version are optional. Wildcards may be used to replace an entire section.
+      Examples:
+       
+        * org.apache.maven
+        
+        * org.apache.maven:bad-plugin
+        
+        * org.apache.maven:my-plugin:badVersion
+        
+        * org.apache.maven:*:1.2
+                
+        []
+
+   * includes - a list of plugin artifacts to include. These are exceptions to the excludes. It is meant to allow wide exclusion rules with wildcards and fine tune using includes. 
+     If nothing has been excluded, then the includes have no effect. In otherwords, includes only subtract from artifacts that matched an exclude rule.
+      
+   * message - an optional message to the user if the rule fails.
+   
+   []
+
+   
+  Sample Plugin Configuration:
+  
++---+
+<project>
+  [...]
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>${project.version}</version>
+        <executions>
+          <execution>
+            <id>enforce-banned-dependencies</id>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <bannedPlugins>
+                  <excludes>
+                    <exclude>org.codehaus.mojo:build-helper-maven-plugin</exclude>
+                  </excludes>
+                </bannedPlugins>
+              </rules>
+              <fail>true</fail>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  [...]
+</project>
++---+
diff --git a/enforcer-rules/src/site/apt/index.apt b/enforcer-rules/src/site/apt/index.apt
index 56aac45..f1d0da9 100644
--- a/enforcer-rules/src/site/apt/index.apt
+++ b/enforcer-rules/src/site/apt/index.apt
@@ -20,7 +20,7 @@
   ------
   Brian Fox
   ------
-  August 2008
+  September 2012
   ------
 
 Standard Rules
@@ -32,15 +32,19 @@
   * {{{./alwaysFail.html}alwaysFail}} - Always fail... used to test plugin configuration.
  
   * {{{./bannedDependencies.html}bannedDependencies}} - enforces that excluded dependencies aren't included.
-
-  * bannedPlugins - enforces that excluded plugins aren't included.
   
+  * {{{./bannedPlugins.html}bannedPlugins}} - enforces that specific plugins aren't included in the build.
+  
+  * {{{./banTransitiveDependencies.html}banTransitiveDependencies}} - enforces that project doesn't have transitive dependencies.
+
   * {{{./dependencyConvergence.html}dependencyConvergence}} - ensure all dependencies converge to the same version.
 
   * {{{./evaluateBeanshell.html}evaluateBeanshell}} - evaluates a beanshell script.
 
   * requireActiveProfile - enforces one or more active profiles.
   
+  * requireEnvironmentVariable - enforces the existence of an environment variable
+  
   * {{{./requireFilesDontExist.html}requireFilesDontExist}} - enforces that the list of files do not exist.
   
   * {{{./requireFilesExist.html}requireFilesExist}} - enforces that the list of files do exist.
@@ -53,7 +57,7 @@
 
   * {{{./requireNoRepositories.html}requireNoRepositories}} - enforces to not include repositories.
 
-  * {{{./requireOS.html}requireOS}} - enforces the OS / CPU Archictecture.
+  * {{{./requireOS.html}requireOS}} - enforces the OS / CPU Architecture.
 
   * {{{./requirePluginVersions.html}requirePluginVersions}} - enforces that all plugins have a specified version.
 
diff --git a/enforcer-rules/src/site/apt/requireNoRepositories.apt.vm b/enforcer-rules/src/site/apt/requireNoRepositories.apt.vm
index 4734997..351e401 100644
--- a/enforcer-rules/src/site/apt/requireNoRepositories.apt.vm
+++ b/enforcer-rules/src/site/apt/requireNoRepositories.apt.vm
@@ -13,8 +13,8 @@
 ~~ "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.    
- 
+~~ under the License.
+
   ------
   Require No Repositories
   ------
@@ -25,30 +25,26 @@
 
 Require No Repositories
 
-   This rule enforces that all plugins have a version defined, either in the plugin or pluginManagement section of the pom or a parent pom.
+   This rule checks that this pom or its parents don't define a repository.
 
    The following parameters are supported by this rule:
-   
-   * message - an optional message to the user if the rule fails.
-   
-   * banLatest - disallow any use of "LATEST" as a version for any plugin. Default = true.
-   
-   * banRelease - disallow any use of "RELEASE" as a version for any plugin. Default = true.
-   
-   * banSnapshots - disallow any use of SNAPSHOT plugins. Default = true.
-   
-   * phases - The comma separated list of phases that should be used to find 
-     lifecycle plugin bindings. The default value is "clean,deploy,site".
-   
-   * additionalPlugins - A list of additional plugins to enforce have versions. These
-     are plugins that may not be in the poms but are used anyway, like help, eclipse etc.
-     The plugins should be specified in the form: group:artifactId.  
-     
-   
+
+   * banRepositories - Whether to ban non-plugin repositories. By default they are banned (true).
+
+   * banPluginRepositories - Whether to ban plugin repositories. By default they are banned (true).
+
+   * allowedRepositories - Specify explicitly allowed non-plugin repositories. This is a list of ids.
+
+   * allowedPluginRepositories - Specify explicitly allowed plugin repositories. This is a list of ids.
+
+   * allowSnapshotRepositories - Whether to allow repositories which only resolve snapshots. By default they are banned (false).
+
+   * allowSnapshotPluginRepositories - Whether to allow plugin repositories which only resolve snapshots. By default they are banned (false).
+
    []
 
    Sample Plugin Configuration (showing some defaults, defaults can be skipped):
-   
+
 +---+
 <project>
   [...]
@@ -60,24 +56,16 @@
         <version>${project.version}</version>
         <executions>
           <execution>
-            <id>enforce-no-repos</id>
+            <id>enforce-no-repositories</id>
             <goals>
               <goal>enforce</goal>
             </goals>
             <configuration>
               <rules>
-                <requirePluginVersions>
-                  <message>Best Practice is to always define plugin versions!</message>
-                  <banLatest>true</banLatest>
-                  <banRelease>true</banRelease>
-                  <banSnapshots>true</banSnapshots>
-                  <phases>clean,deploy,site</phases>
-                  <additionalPlugins>
-                    <additionalPlugin>org.apache.maven.plugins:maven-eclipse-plugin</additionalPlugin>
-                    <additionalPlugin>org.apache.maven.plugins:maven-ide-plugin</additionalPlugin>
-                  </additionalPlugins>
-                </requirePluginVersions>
-              </rules>    
+                <requireNoRepositories>
+                  <message>Best Practice is to never define repositories in pom.xml (use a repository manager instead)</message>
+                </requireNoRepositories>
+              </rules>
             </configuration>
           </execution>
         </executions>
@@ -86,4 +74,4 @@
   </build>
   [...]
 </project>
-+---+  
\ No newline at end of file
++---+
\ No newline at end of file
diff --git a/enforcer-rules/src/site/apt/requireProperty.apt.vm b/enforcer-rules/src/site/apt/requireProperty.apt.vm
index 07c62f9..0023056 100644
--- a/enforcer-rules/src/site/apt/requireProperty.apt.vm
+++ b/enforcer-rules/src/site/apt/requireProperty.apt.vm
@@ -27,18 +27,20 @@
 
   This rule can enforce that a declared property is set and optionally evaluate it against a regular expression.
 
+  The following parameters are supported by this rule:
+   
+  * property - the property to evaluate.
+   
+  * message - an optional message to the user if the rule fails. Default is: "Property 'xxx' is required for this build".	
+   
+  * regex - a regular expression used to check the value of the property.
+   
+  * regexMessage - an optional message to the user if the regex check fails.
 
-   The following parameters are supported by this rule:
-   
-   * property - the property to evaluate.
-   
-   * message - an optional message to the user if the rule fails. Default is: "Property 'xxx' is required for this build".	
-   
-   * regex - a regular expression used to check the value of the property.
-   
-   * regexMessage - an optional message to the user if the regex check fails.
-   
-   []
+  []
+
+  The regex is applied to the entire value of the property (i.e. using the regex "match" method),
+  and not just a substring of the property value.
 
   Sample Plugin Configuration:
   
@@ -61,9 +63,9 @@
               <rules>
                 <requireProperty>
                   <property>basedir</property>
-                  <message>You must have a basedir!</message>
-                  <regex>\d</regex>
-                  <regexMessage>You must have a digit in your baseDir!</regexMessage>
+                  <message>You must set a basedir property!</message>
+                  <regex>.*\d.*</regex>
+                  <regexMessage>The basedir property must contain at least one digit.</regexMessage>
                 </requireProperty>
                 <requireProperty>
                   <property>project.version</property>
diff --git a/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireEnvironmentVariable.java b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireEnvironmentVariable.java
new file mode 100755
index 0000000..8b4a236
--- /dev/null
+++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/TestRequireEnvironmentVariable.java
@@ -0,0 +1,111 @@
+package org.apache.maven.plugins.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 junit.framework.TestCase;

+import org.apache.maven.enforcer.rule.api.EnforcerRuleException;

+import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;

+

+/**

+ * Unit test for {@link RequireEnvironmentVariable}}

+ *

+ * @author <a href='mailto:marvin[at]marvinformatics[dot]com'>Marvin Froeder</a>

+ */

+public class TestRequireEnvironmentVariable

+    extends TestCase

+{

+

+    /**

+     * Test rule.

+     *

+     * @throws EnforcerRuleException the enforcer rule exception

+     */

+    public void testRule()

+        throws EnforcerRuleException

+    {

+        MockProject project = new MockProject();

+        project.setProperty( "testProp", "This is a test." );

+        EnforcerRuleHelper helper = EnforcerTestUtils.getHelper( project );

+

+        RequireEnvironmentVariable rule = new RequireEnvironmentVariable();

+        // this env variable should not be set

+        rule.variableName = "JUNK";

+

+        try

+        {

+            rule.execute( helper );

+            fail( "Expected an exception." );

+        }

+        catch ( EnforcerRuleException e )

+        {

+            // expected to catch this.

+        }

+

+        // PATH shall be common to windows and linux

+        rule.variableName = "PATH";

+        try

+        {

+            rule.execute( helper );

+        }

+        catch ( EnforcerRuleException e )

+        {

+            fail( "This should not throw an exception" );

+        }

+    }

+

+    /**

+     * Test rule with regex.

+     *

+     * @throws EnforcerRuleException the enforcer rule exception

+     */

+    public void testRuleWithRegex()

+        throws EnforcerRuleException

+    {

+        EnforcerRuleHelper helper = EnforcerTestUtils.getHelper();

+

+        RequireEnvironmentVariable rule = new RequireEnvironmentVariable();

+        rule.variableName = "PATH";

+        // This expression should not match the property

+        // value

+        rule.regex = "[^abc]";

+

+        try

+        {

+            rule.execute( helper );

+            fail( "Expected an exception." );

+        }

+        catch ( EnforcerRuleException e )

+        {

+            // expected to catch this.

+        }

+

+        // can't really predict what a PATH will looks like, just enforce it ain't empty

+        rule.regex = ".{1,}";

+        try

+        {

+            rule.execute( helper );

+        }

+        catch ( EnforcerRuleException e )

+        {

+            fail( "This should not throw an exception" );

+        }

+    }

+

+}

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/plugins/enforcer/utils/TestArtifactMatcher.java
new file mode 100644
index 0000000..839b0cc
--- /dev/null
+++ b/enforcer-rules/src/test/java/org/apache/maven/plugins/enforcer/utils/TestArtifactMatcher.java
@@ -0,0 +1,141 @@
+package org.apache.maven.plugins.enforcer.utils;
+
+/*
+ * 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.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+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 junit.framework.TestCase;
+
+public class TestArtifactMatcher extends TestCase
+{
+	private ArtifactMatcher matcher;
+	
+	Collection<String> patterns = new ArrayList<String>();
+	
+	Collection<String> ignorePatterns = new ArrayList<String>();
+	
+	public void testPatternInvalidInput() throws InvalidVersionSpecificationException
+	{
+		try
+		{
+			new Pattern(null);
+			fail("NullPointerException expected.");
+		}
+		catch(NullPointerException e){}
+		
+		try
+		{
+			new Pattern("a:b:c:d:e:f");
+			fail("IllegalArgumentException expected.");
+		}
+		catch(IllegalArgumentException e){}
+		
+		try
+		{
+			new Pattern("a::");
+			fail("IllegalArgumentException expected.");
+		}
+		catch(IllegalArgumentException e){}
+		
+		try
+		{
+			Pattern p = new Pattern("*");
+			p.match(null);
+			fail("NullPointerException expected.");
+		}
+		catch(NullPointerException e){}
+	}
+	
+	public void testPattern() throws InvalidVersionSpecificationException
+	{
+		executePatternMatch("groupId:artifactId:1.0:jar:compile", "groupId", "artifactId", "1.0", "compile", "jar", true);
+		
+		executePatternMatch("groupId:artifactId:1.0:jar:compile", "groupId", "artifactId", "1.0", "", "", true);
+		
+		executePatternMatch("groupId:artifactId:1.0", "groupId", "artifactId", "1.0", "", "", true);
+		
+		executePatternMatch("groupId:artifactId:1.0", "groupId", "artifactId", "1.1", "", "", true);
+		
+		executePatternMatch("groupId:artifactId:[1.0]", "groupId", "artifactId", "1.1", "", "", false);
+		
+		executePatternMatch("groupId:*:1.0", "groupId", "artifactId", "1.0", "test", "", true);
+		
+		executePatternMatch("*:*:1.0", "groupId", "artifactId", "1.0", "", "", true);
+		
+		executePatternMatch("*:artifactId:*", "groupId", "artifactId", "1.0", "", "", true);
+		
+		executePatternMatch("*", "groupId", "artifactId", "1.0", "", "", true);
+	}
+	
+	public void testMatch() throws InvalidVersionSpecificationException
+	{
+		patterns.add("groupId:artifactId:1.0");
+		patterns.add("*:anotherArtifact");
+		
+		ignorePatterns.add("badGroup:*:*:test");
+		ignorePatterns.add("*:anotherArtifact:1.1");
+		
+		matcher = new ArtifactMatcher(patterns, ignorePatterns);
+		
+		executeMatch(matcher, "groupId", "artifactId", "1.0", "", "", true);	
+		
+		executeMatch(matcher, "groupId", "anotherArtifact", "1.0", "", "", true);	
+		
+		executeMatch(matcher, "badGroup", "artifactId", "1.0", "", "test", false);
+		
+		executeMatch(matcher, "badGroup", "anotherArtifact", "1.0", "", "", true);	
+		
+		executeMatch(matcher, "groupId", "anotherArtifact", "1.1", "", "", false);	
+	}
+	
+	private void executePatternMatch(final String pattern, final String groupId, final String artifactId,
+			final String versionRange, final String scope, final String type, boolean expectedResult)
+			throws InvalidVersionSpecificationException
+	{
+		assertEquals(expectedResult, new ArtifactMatcher.Pattern(pattern).match(createMockArtifact(groupId, artifactId, versionRange, scope, type)));
+	}
+	
+	
+	private void executeMatch(final ArtifactMatcher matcher, final String groupId, final String artifactId,
+			final String versionRange, final String scope, final String type, final boolean expectedResult) throws InvalidVersionSpecificationException
+	{
+		assertEquals(expectedResult, matcher.match(createMockArtifact(groupId, artifactId, versionRange, scope, type)));
+	}
+	
+	
+	private static Artifact createMockArtifact(final String groupId, final String artifactId,
+			final String versionRange, final String scope, final String type)
+	{
+		ArtifactHandler artifactHandler = new DefaultArtifactHandler();
+		
+		VersionRange version = VersionRange.createFromVersion(versionRange);
+		return new DefaultArtifact(groupId, artifactId, version, scope, type, "", artifactHandler);
+	}
+}
diff --git a/maven-enforcer-plugin/pom.xml b/maven-enforcer-plugin/pom.xml
index 15fe503..6c20cdf 100644
--- a/maven-enforcer-plugin/pom.xml
+++ b/maven-enforcer-plugin/pom.xml
@@ -29,41 +29,10 @@
 
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-enforcer-plugin</artifactId>
-  <version>1.2</version>
   <packaging>maven-plugin</packaging>
 
   <name>Maven Enforcer Plugin</name>
   <description>The Loving Iron Fist of Maven</description>
-  <url>http://maven.apache.org/plugins/maven-enforcer-plugin/</url>
-  <inceptionYear>2007</inceptionYear>
-
-  <developers>
-    <developer>
-      <id>brianf</id>
-      <name>Brian Fox</name>
-      <email>brianf@apache.org</email>
-      <roles>
-        <role>Lead Developer</role>
-      </roles>
-      <timezone>5</timezone>
-    </developer>
-  </developers>
-
-  <prerequisites>
-    <!--because of the encoding fixes, I need a new plexus-utils. The new plexus utils can only be used in 2.0.6 or later: http://jira.codehaus.org/browse/MNG-2892 -->
-    <maven>2.0.6</maven>
-  </prerequisites>
-
-  <issueManagement>
-    <system>JIRA</system>
-    <url>http://jira.codehaus.org/browse/MENFORCER</url>
-  </issueManagement>
-  <distributionManagement>
-    <site>
-      <id>apache.website</id>
-      <url>${site.deploy.url}/plugins/maven-enforcer-plugin</url>
-    </site>
-  </distributionManagement>
 
   <dependencies>
     <dependency>
@@ -107,6 +76,12 @@
       <groupId>org.apache.maven.shared</groupId>
       <artifactId>maven-plugin-testing-harness</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.maven.plugin-tools</groupId>
+      <artifactId>maven-plugin-annotations</artifactId>
+      <version>${mavenPluginPluginVersion}</version>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -125,23 +100,24 @@
         </executions>
       </plugin>
       <plugin>
-        <artifactId>maven-site-plugin</artifactId>
-        <configuration>
-          <stagingSiteURL>
-            scp://people.apache.org/www/maven.apache.org/staging
-          </stagingSiteURL>
-        </configuration>
-      </plugin>
-      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-plugin-plugin</artifactId>
+        <configuration>
+          <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+        </configuration>
         <executions>
           <execution>
-            <id>generated-helpmojo</id>
+            <id>generate-helpmojo</id>
             <goals>
               <goal>helpmojo</goal>
             </goals>
           </execution>
+          <execution>
+            <id>mojo-descriptor</id>
+            <goals>
+              <goal>descriptor</goal>
+            </goals>
+          </execution>
         </executions>
       </plugin>
     </plugins>
@@ -163,7 +139,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-plugin-plugin</artifactId>
-        <version>${maven.plugin.plugin.version}</version>
+        <version>${mavenPluginPluginVersion}</version>
       </plugin>
     </plugins>
   </reporting>
diff --git a/maven-enforcer-plugin/src/it/ban-transitive-dependencies-fail/invoker.properties b/maven-enforcer-plugin/src/it/ban-transitive-dependencies-fail/invoker.properties
new file mode 100644
index 0000000..c21e972
--- /dev/null
+++ b/maven-enforcer-plugin/src/it/ban-transitive-dependencies-fail/invoker.properties
@@ -0,0 +1 @@
+invoker.buildResult = failure
diff --git a/maven-enforcer-plugin/src/it/ban-transitive-dependencies-fail/pom.xml b/maven-enforcer-plugin/src/it/ban-transitive-dependencies-fail/pom.xml
new file mode 100644
index 0000000..d4ea8e8
--- /dev/null
+++ b/maven-enforcer-plugin/src/it/ban-transitive-dependencies-fail/pom.xml
@@ -0,0 +1,71 @@
+<?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>ban-transitive-fail-test</artifactId>
+  <version>1.0</version>
+
+  <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>
+                <BanTransitiveDependencies>
+                  <excludes>
+                    <exclude>junit:junit</exclude>
+                    <exclude>classworlds:classworlds</exclude>
+                    <exclude>org.codehaus.plexus:plexus-io</exclude>
+                  </excludes>
+                </BanTransitiveDependencies>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-archiver</artifactId>
+      <version>2.1.1</version>
+    </dependency>  
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+      <version>3.0</version>
+    </dependency>  
+  </dependencies>
+
+</project>
diff --git a/maven-enforcer-plugin/src/it/ban-transitive-dependencies/pom.xml b/maven-enforcer-plugin/src/it/ban-transitive-dependencies/pom.xml
new file mode 100644
index 0000000..21f7db4
--- /dev/null
+++ b/maven-enforcer-plugin/src/it/ban-transitive-dependencies/pom.xml
@@ -0,0 +1,70 @@
+<?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>ban-transitive-test</artifactId>
+  <version>1.0</version>
+
+  <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>
+                <BanTransitiveDependencies>
+                  <excludes>
+                    <exclude>org.codehaus.plexus:plexus-container-default</exclude>
+                    <exclude>org.codehaus.plexus:plexus-io</exclude>
+                  </excludes>
+                </BanTransitiveDependencies>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-archiver</artifactId>
+      <version>2.1.1</version>
+    </dependency>  
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+      <version>3.0</version>
+    </dependency>  
+  </dependencies>
+
+</project>
diff --git a/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/DisplayInfoMojo.java b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/DisplayInfoMojo.java
index 9ef7b32..478ee75 100644
--- a/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/DisplayInfoMojo.java
+++ b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/DisplayInfoMojo.java
@@ -24,6 +24,8 @@
 import org.apache.maven.execution.RuntimeInformation;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.path.PathTranslator;
 import org.codehaus.plexus.PlexusConstants;
@@ -36,11 +38,10 @@
 /**
  * This goal displays the current platform information.
  *
- * @goal display-info
  * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
  * @version $Id$
- * @threadSafe
  */
+@Mojo( name = "display-info", threadSafe = true )
 public class DisplayInfoMojo
     extends AbstractMojo
     implements Contextualizable
@@ -48,26 +49,20 @@
 
     /**
      * Path Translator needed by the ExpressionEvaluator
-     *
-     * @component role="org.apache.maven.project.path.PathTranslator"
      */
+    @Component( role = PathTranslator.class )
     protected PathTranslator translator;
 
     /**
      * The MavenSession
-     *
-     * @parameter default-value="${session}"
-     * @readonly
      */
+    @Component
     protected MavenSession session;
 
     /**
      * POM
-     *
-     * @parameter default-value="${project}"
-     * @readonly
-     * @required
      */
+    @Component
     protected MavenProject project;
 
     // set by the contextualize method. Only way to get the
@@ -97,13 +92,11 @@
                                + RequireJavaVersion.normalizeJDKVersion( SystemUtils.JAVA_VERSION_TRIMMED ) );
             RequireOS os = new RequireOS();
             os.displayOSInfo( getLog(), true );
-
         }
         catch ( ComponentLookupException e )
         {
             getLog().warn( "Unable to Lookup component: " + e.getLocalizedMessage() );
         }
-
     }
 
 }
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 c280063..7d8c785 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
@@ -30,6 +30,11 @@
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugins.annotations.Component;
+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.project.MavenProject;
 import org.apache.maven.project.path.PathTranslator;
 import org.codehaus.plexus.PlexusConstants;
@@ -42,13 +47,11 @@
  * This goal executes the defined enforcer-rules once per
  * module.
  * 
- * @requiresDependencyResolution test
- * @goal enforce
- * @phase validate
- * @threadSafe
  * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
  * @version $Id$
  */
+@Mojo( name = "enforce", defaultPhase = LifecyclePhase.VALIDATE, threadSafe = true,
+                requiresDependencyResolution = ResolutionScope.TEST )
 public class EnforceMojo
     extends AbstractMojo
     implements Contextualizable
@@ -56,74 +59,59 @@
 
     /**
      * Path Translator needed by the ExpressionEvaluator
-     * 
-     * @component role="org.apache.maven.project.path.PathTranslator"
      */
+    @Component( role = PathTranslator.class )
     protected PathTranslator translator;
 
     /**
      * The MavenSession
-     * 
-     * @parameter expression="${session}"
-     * @readonly
      */
+    @Component
     protected MavenSession session;
 
     /**
      * POM
-     * 
-     * @parameter expression="${project}"
-     * @readonly
-     * @required
      */
+    @Component
     protected MavenProject project;
 
     /**
      * Flag to fail the build if a version check fails.
-     * 
-     * @parameter expression="${enforcer.fail}"
-     *            default-value="true"
      */
+    @Parameter( property = "enforcer.fail", defaultValue = "true" )
     protected boolean fail = true;
 
     /**
      * Flag to easily skip all checks
-     * 
-     * @parameter expression="${enforcer.skip}"
-     *            default-value="false"
      */
+    @Parameter( property = "enforcer.skip", defaultValue = "false" )
     protected boolean skip = false;
 
     /**
      * Fail on the first rule that doesn't pass
-     * 
-     * @parameter expression="${enforcer.failFast}"
-     *            default-value="false"
      */
+    @Parameter( property = "enforcer.failFast", defaultValue = "false" )
     protected boolean failFast = false;
 
     /**
      * Array of objects that implement the EnforcerRule
      * interface to execute.
-     * 
-     * @parameter
-     * @required
      */
+    @Parameter( required = true )
     private EnforcerRule[] rules;
     
     /**
      * Use this flag to disable rule result caching. This will cause
      * all rules to execute on each project even if the rule indicates it can
      * safely be cached.
-     * @parameter expression="${enforcer.ignoreCache}"
-     *  default-value="false"
      */
-     protected boolean ignoreCache = false;
+    @Parameter( property = "enforcer.ignoreCache", defaultValue = "false" )
+    protected boolean ignoreCache = false;
     
     /**
      * This is a static variable used to persist the cached results across plugin invocations.
      */
-     protected static Hashtable<String, EnforcerRule> cache = new Hashtable<String, EnforcerRule>();
+    protected static Hashtable<String, EnforcerRule> cache = new Hashtable<String, EnforcerRule>();
 
     
     // set by the contextualize method. Only way to get the
diff --git a/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/EnforceOnceMojo.java b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/EnforceOnceMojo.java
index 7d6f17a..27249ff 100644
--- a/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/EnforceOnceMojo.java
+++ b/maven-enforcer-plugin/src/main/java/org/apache/maven/plugins/enforcer/EnforceOnceMojo.java
@@ -1,6 +1,9 @@
 package org.apache.maven.plugins.enforcer;
 
 import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.ResolutionScope;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -25,12 +28,11 @@
  * This goal has been deprecated.
  * 
  * @deprecated
- * @goal enforce-once
- * @phase validate
- * @requiresDependencyResolution test
  * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
  * @version $Id$
  */
+@Mojo( name = "enforce-once", defaultPhase = LifecyclePhase.VALIDATE, threadSafe = true,
+                requiresDependencyResolution = ResolutionScope.TEST )
 public class EnforceOnceMojo
     extends EnforceMojo
 {
diff --git a/maven-enforcer-plugin/src/site/apt/usage.apt.vm b/maven-enforcer-plugin/src/site/apt/usage.apt.vm
index 2c51148..ce8d111 100644
--- a/maven-enforcer-plugin/src/site/apt/usage.apt.vm
+++ b/maven-enforcer-plugin/src/site/apt/usage.apt.vm
@@ -43,13 +43,13 @@
 
    These goals are meant to be bound to a lifecycle phase and configured in your
    <<<pom.xml>>>. The enforcers execute the configured rules to check for certain constraints. 
-   The available standard rules are described {{{rules/index.html}here}}. Besides the rules to execute, these goals support three options:
+   The available standard rules are described {{{./rules/index.html}here}}. Besides the rules to execute, these goals support three options:
    
-   * {{{enforce-mojo.html#skip}skip}} - a quick way to skip checks via a profile or using <<<-Denforcer.skip=true>>> from the command line.
+   * {{{./enforce-mojo.html#skip}skip}} - a quick way to skip checks via a profile or using <<<-Denforcer.skip=true>>> from the command line.
    
-   * {{{enforce-mojo.html#fail}fail}} - if the goal should fail the build when a rule fails. The default is <<<true>>>. If false, the errors will be logged as warnings.
+   * {{{./enforce-mojo.html#fail}fail}} - if the goal should fail the build when a rule fails. The default is <<<true>>>. If false, the errors will be logged as warnings.
    
-   * {{{enforce-mojo.html#failFast}failFast}} - if the goal should stop checking after the first failure. The default is <<<false>>>.
+   * {{{./enforce-mojo.html#failFast}failFast}} - if the goal should stop checking after the first failure. The default is <<<false>>>.
    
    []
    
diff --git a/pom.xml b/pom.xml
index 206f641..c202756 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <artifactId>maven-parent</artifactId>
     <groupId>org.apache.maven</groupId>
-    <version>21</version>
+    <version>22</version>
     <relativePath>../pom/maven/pom.xml</relativePath>
   </parent>
   <groupId>org.apache.maven.enforcer</groupId>
@@ -122,6 +122,7 @@
   </mailingLists>
 
   <prerequisites>
+    <!--because of the encoding fixes, I need a new plexus-utils. The new plexus utils can only be used in 2.0.6 or later: http://jira.codehaus.org/browse/MNG-2892 -->
     <maven>2.0.6</maven>
   </prerequisites>
 
@@ -152,7 +153,7 @@
   </distributionManagement>
   <properties>
     <maven.version>2.0.9</maven.version>
-    <maven.plugin.plugin.version>2.7</maven.plugin.plugin.version>
+    <mavenPluginPluginVersion>3.2</mavenPluginPluginVersion>
     <site.deploy.url>scp://people.apache.org/www/maven.apache.org</site.deploy.url>
   </properties>
 
@@ -246,15 +247,8 @@
     <pluginManagement>
       <plugins>
         <plugin>
-          <artifactId>maven-compiler-plugin</artifactId>
-          <configuration>
-            <source>1.5</source>
-            <target>1.5</target>
-          </configuration>
-        </plugin>
-        <plugin>
           <artifactId>maven-plugin-plugin</artifactId>
-          <version>${maven.plugin.plugin.version}</version>
+          <version>${mavenPluginPluginVersion}</version>
         </plugin>
         <plugin>
           <artifactId>maven-release-plugin</artifactId>
@@ -273,26 +267,21 @@
         <artifactId>cobertura-maven-plugin</artifactId>
         <version>2.4</version>
       </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-javadoc-plugin</artifactId>
-        <version>2.8.1</version>
-        <configuration>
-           <tagletArtifacts>
-             <tagletArtifact>
-                <groupId>org.apache.maven.plugin-tools</groupId>
-                <artifactId>maven-plugin-tools-javadoc</artifactId>
-                <version>2.6</version>
-             </tagletArtifact>
-             <tagletArtifact>
-               <groupId>org.codehaus.plexus</groupId>
-               <artifactId>plexus-javadoc</artifactId>
-               <version>1.0</version>
-             </tagletArtifact>
-           </tagletArtifacts>
-          </configuration>
-       </plugin>
     </plugins>
   </reporting>
 
+  <profiles>
+    <profile>
+      <id>reporting</id>
+      <reporting>
+        <plugins>
+          <plugin><!-- TODO remove when upgrading parent to 23 -->
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-project-info-reports-plugin</artifactId>
+            <version>2.6</version>
+          </plugin>
+        </plugins>
+      </reporting>
+    </profile>
+  </profiles>
 </project>