View Javadoc
1   package org.apache.maven.plugins.enforcer;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.artifact.Artifact;
23  import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
24  import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
25  import org.apache.maven.plugin.logging.Log;
26  import org.apache.maven.project.MavenProject;
27  import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
28  import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
29  import org.apache.maven.shared.dependency.graph.DependencyNode;
30  import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
31  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
32  import java.util.HashSet;
33  import java.util.Set;
34  
35  /**
36   * Abstract Rule for banning dependencies.
37   *
38   * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
39   * @version $Id: AbstractBanDependencies.java 1630934 2014-10-10 16:35:26Z khmarbaise $
40   */
41  public abstract class AbstractBanDependencies
42      extends AbstractNonCacheableEnforcerRule
43  {
44  
45      /** Specify if transitive dependencies should be searched (default) or only look at direct dependencies. */
46      private boolean searchTransitive = true;
47  
48      private transient DependencyGraphBuilder graphBuilder;
49  
50      /**
51       * Execute the rule.
52       *
53       * @param helper the helper
54       * @throws EnforcerRuleException the enforcer rule exception
55       */
56      public void execute( EnforcerRuleHelper helper )
57          throws EnforcerRuleException
58      {
59  
60          // get the project
61          MavenProject project = null;
62          try
63          {
64              project = (MavenProject) helper.evaluate( "${project}" );
65          }
66          catch ( ExpressionEvaluationException eee )
67          {
68              throw new EnforcerRuleException( "Unable to retrieve the MavenProject: ", eee );
69          }
70  
71          try
72          {
73              graphBuilder = (DependencyGraphBuilder) helper.getComponent( DependencyGraphBuilder.class );
74          }
75          catch ( ComponentLookupException e )
76          {
77              // real cause is probably that one of the Maven3 graph builder could not be initiated and fails with a
78              // ClassNotFoundException
79              try
80              {
81                  graphBuilder =
82                      (DependencyGraphBuilder) helper.getComponent( DependencyGraphBuilder.class.getName(), "maven2" );
83              }
84              catch ( ComponentLookupException e1 )
85              {
86                  throw new EnforcerRuleException( "Unable to lookup DependencyGraphBuilder: ", e );
87              }
88          }
89  
90          // get the correct list of dependencies
91          Set<Artifact> dependencies = getDependenciesToCheck( project );
92  
93          // look for banned dependencies
94          Set<Artifact> foundExcludes = checkDependencies( dependencies, helper.getLog() );
95  
96          // if any are found, fail the check but list all of them
97          if ( foundExcludes != null && !foundExcludes.isEmpty() )
98          {
99              String message = getMessage();
100 
101             StringBuilder buf = new StringBuilder();
102             if ( message != null )
103             {
104                 buf.append( message + "\n" );
105             }
106             for ( Artifact artifact : foundExcludes )
107             {
108                 buf.append( getErrorMessage( artifact ) );
109             }
110             message = buf.toString() + "Use 'mvn dependency:tree' to locate the source of the banned dependencies.";
111 
112             throw new EnforcerRuleException( message );
113         }
114 
115     }
116 
117     protected CharSequence getErrorMessage( Artifact artifact )
118     {
119         return "Found Banned Dependency: " + artifact.getId() + "\n";
120     }
121 
122     protected Set<Artifact> getDependenciesToCheck( MavenProject project )
123     {
124         Set<Artifact> dependencies = null;
125         try
126         {
127             DependencyNode node = graphBuilder.buildDependencyGraph( project, null );
128             if ( searchTransitive )
129             {
130                 dependencies = getAllDescendants( node );
131             }
132             else if ( node.getChildren() != null )
133             {
134                 dependencies = new HashSet<Artifact>();
135                 for ( DependencyNode depNode : node.getChildren() )
136                 {
137                     dependencies.add( depNode.getArtifact() );
138                 }
139             }
140         }
141         catch ( DependencyGraphBuilderException e )
142         {
143             // otherwise we need to change the signature of this protected method
144             throw new RuntimeException( e );
145         }
146         return dependencies;
147     }
148 
149     private Set<Artifact> getAllDescendants( DependencyNode node )
150     {
151         Set<Artifact> children = null;
152         if ( node.getChildren() != null )
153         {
154             children = new HashSet<Artifact>();
155             for ( DependencyNode depNode : node.getChildren() )
156             {
157                 children.add( depNode.getArtifact() );
158                 Set<Artifact> subNodes = getAllDescendants( depNode );
159                 if ( subNodes != null )
160                 {
161                     children.addAll( subNodes );
162                 }
163             }
164         }
165         return children;
166     }
167 
168     /**
169      * Checks the set of dependencies against the list of excludes.
170      *
171      * @param dependencies the dependencies
172      * @param log the log
173      * @return the sets the
174      * @throws EnforcerRuleException the enforcer rule exception
175      */
176     protected abstract Set<Artifact> checkDependencies( Set<Artifact> dependencies, Log log )
177         throws EnforcerRuleException;
178 
179     /**
180      * Checks if is search transitive.
181      *
182      * @return the searchTransitive
183      */
184     public boolean isSearchTransitive()
185     {
186         return this.searchTransitive;
187     }
188 
189     /**
190      * Sets the search transitive.
191      *
192      * @param theSearchTransitive the searchTransitive to set
193      */
194     public void setSearchTransitive( boolean theSearchTransitive )
195     {
196         this.searchTransitive = theSearchTransitive;
197     }
198 
199 }