Coverage Report - org.apache.maven.plugins.enforcer.DependencyConvergence
 
Classes in this File Line Coverage Branch Coverage Complexity
DependencyConvergence
0%
0/67
0%
0/20
3.2
 
 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  
 import java.util.ArrayList;
 22  
 import java.util.Collections;
 23  
 import java.util.List;
 24  
 
 25  
 import org.apache.maven.artifact.Artifact;
 26  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 27  
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 28  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 29  
 import org.apache.maven.artifact.resolver.ArtifactCollector;
 30  
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 31  
 import org.apache.maven.enforcer.rule.api.EnforcerRule;
 32  
 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
 33  
 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
 34  
 import org.apache.maven.plugin.logging.Log;
 35  
 import org.apache.maven.plugins.enforcer.utils.DependencyVersionMap;
 36  
 import org.apache.maven.project.MavenProject;
 37  
 import org.apache.maven.shared.dependency.tree.DependencyNode;
 38  
 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
 39  
 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
 40  
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 41  
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 42  
 import org.codehaus.plexus.i18n.I18N;
 43  
 
 44  
 /**
 45  
  * @author <a href="mailto:rex@e-hoffman.org">Rex Hoffman</a>
 46  
  */
 47  0
 public class DependencyConvergence
 48  
     implements EnforcerRule
 49  
 {
 50  
 
 51  
     private static Log log;
 52  
 
 53  
     private static I18N i18n;
 54  
     
 55  
     private boolean uniqueVersions; 
 56  
 
 57  
     public void setUniqueVersions( boolean uniqueVersions )
 58  
     {
 59  0
         this.uniqueVersions = uniqueVersions;
 60  0
     }
 61  
     
 62  
     /**
 63  
      * Uses the {@link EnforcerRuleHelper} to populate the values of the
 64  
      * {@link DependencyTreeBuilder#buildDependencyTree(MavenProject, ArtifactRepository, ArtifactFactory, ArtifactMetadataSource, ArtifactFilter, ArtifactCollector)}
 65  
      * factory method. <br/>
 66  
      * This method simply exists to hide all the ugly lookup that the {@link EnforcerRuleHelper} has to do.
 67  
      * 
 68  
      * @param helper
 69  
      * @return a Dependency Node which is the root of the project's dependency tree
 70  
      * @throws EnforcerRuleException
 71  
      */
 72  
     private DependencyNode getNode( EnforcerRuleHelper helper )
 73  
         throws EnforcerRuleException
 74  
     {
 75  
         try
 76  
         {
 77  0
             MavenProject project = (MavenProject) helper.evaluate( "${project}" );
 78  0
             DependencyTreeBuilder dependencyTreeBuilder =
 79  
                 (DependencyTreeBuilder) helper.getComponent( DependencyTreeBuilder.class );
 80  0
             ArtifactRepository repository = (ArtifactRepository) helper.evaluate( "${localRepository}" );
 81  0
             ArtifactFactory factory = (ArtifactFactory) helper.getComponent( ArtifactFactory.class );
 82  0
             ArtifactMetadataSource metadataSource =
 83  
                 (ArtifactMetadataSource) helper.getComponent( ArtifactMetadataSource.class );
 84  0
             ArtifactCollector collector = (ArtifactCollector) helper.getComponent( ArtifactCollector.class );
 85  0
             ArtifactFilter filter = null; // we need to evaluate all scopes
 86  0
             DependencyNode node =
 87  
                 dependencyTreeBuilder.buildDependencyTree( project, repository, factory, metadataSource, filter,
 88  
                                                            collector );
 89  0
             return node;
 90  
         }
 91  0
         catch ( ExpressionEvaluationException e )
 92  
         {
 93  0
             throw new EnforcerRuleException( "Unable to lookup an expression " + e.getLocalizedMessage(), e );
 94  
         }
 95  0
         catch ( ComponentLookupException e )
 96  
         {
 97  0
             throw new EnforcerRuleException( "Unable to lookup a component " + e.getLocalizedMessage(), e );
 98  
         }
 99  0
         catch ( DependencyTreeBuilderException e )
 100  
         {
 101  0
             throw new EnforcerRuleException( "Could not build dependency tree " + e.getLocalizedMessage(), e );
 102  
         }
 103  
     }
 104  
 
 105  
     public void execute( EnforcerRuleHelper helper )
 106  
         throws EnforcerRuleException
 107  
     {
 108  0
         if ( log == null )
 109  
         {
 110  0
             log = helper.getLog();
 111  
         }
 112  
         try
 113  
         {
 114  0
             if ( i18n == null )
 115  
             {
 116  0
                 i18n = (I18N) helper.getComponent( I18N.class );
 117  
             }
 118  0
             DependencyNode node = getNode( helper );
 119  0
             DependencyVersionMap visitor = new DependencyVersionMap( log );
 120  0
             visitor.setUniqueVersions( uniqueVersions );
 121  0
             node.accept( visitor );
 122  0
             List<CharSequence> errorMsgs = new ArrayList<CharSequence>();
 123  0
             errorMsgs.addAll( getConvergenceErrorMsgs( visitor.getConflictedVersionNumbers() ) );
 124  0
             for ( CharSequence errorMsg : errorMsgs )
 125  
             {
 126  0
                 log.error( errorMsg );
 127  
             }
 128  0
             if ( errorMsgs.size() > 0 )
 129  
             {
 130  0
                 throw new EnforcerRuleException( "Failed while enforcing releasability the error(s) are " + errorMsgs );
 131  
             }
 132  
         }
 133  0
         catch ( ComponentLookupException e )
 134  
         {
 135  0
             throw new EnforcerRuleException( "Unable to lookup a component " + e.getLocalizedMessage(), e );
 136  
         }
 137  0
         catch ( Exception e )
 138  
         {
 139  0
             throw new EnforcerRuleException( e.getLocalizedMessage(), e );
 140  0
         }
 141  0
     }
 142  
 
 143  
     private String getFullArtifactName( Artifact artifact )
 144  
     {
 145  0
         return artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion();
 146  
     }
 147  
 
 148  
     private StringBuilder buildTreeString( DependencyNode node )
 149  
     {
 150  0
         List<String> loc = new ArrayList<String>();
 151  0
         DependencyNode currentNode = node;
 152  0
         while ( currentNode != null )
 153  
         {
 154  0
             loc.add( getFullArtifactName( currentNode.getArtifact() ) );
 155  0
             currentNode = currentNode.getParent();
 156  
         }
 157  0
         Collections.reverse( loc );
 158  0
         StringBuilder builder = new StringBuilder();
 159  0
         for ( int i = 0; i < loc.size(); i++ )
 160  
         {
 161  0
             for ( int j = 0; j < i; j++ )
 162  
             {
 163  0
                 builder.append( "  " );
 164  
             }
 165  0
             builder.append( "+-" + loc.get( i ) );
 166  0
             builder.append( "\n" );
 167  
         }
 168  0
         return builder;
 169  
     }
 170  
 
 171  
     private List<String> getConvergenceErrorMsgs( List<List<DependencyNode>> errors )
 172  
     {
 173  0
         List<String> errorMsgs = new ArrayList<String>();
 174  0
         for ( List<DependencyNode> nodeList : errors )
 175  
         {
 176  0
             errorMsgs.add( buildConvergenceErrorMsg( nodeList ) );
 177  
         }
 178  0
         return errorMsgs;
 179  
     }
 180  
 
 181  
     private String buildConvergenceErrorMsg( List<DependencyNode> nodeList )
 182  
     {
 183  0
         StringBuilder builder = new StringBuilder();
 184  0
         builder.append( "\nDependency convergence error for " + getFullArtifactName( nodeList.get( 0 ).getArtifact() )
 185  
             + " paths to dependency are:\n" );
 186  0
         if ( nodeList.size() > 0 )
 187  
         {
 188  0
             builder.append( buildTreeString( nodeList.get( 0 ) ) );
 189  
         }
 190  0
         for ( DependencyNode node : nodeList.subList( 1, nodeList.size() ) )
 191  
         {
 192  0
             builder.append( "and\n" );
 193  0
             builder.append( buildTreeString( node ) );
 194  
         }
 195  0
         return builder.toString();
 196  
     }
 197  
 
 198  
     /**
 199  
      * If your rule is cacheable, you must return a unique id when parameters or conditions change that would cause the
 200  
      * result to be different. Multiple cached results are stored based on their id. The easiest way to do this is to
 201  
      * return a hash computed from the values of your parameters. If your rule is not cacheable, then the result here is
 202  
      * not important, you may return anything.
 203  
      */
 204  
     public String getCacheId()
 205  
     {
 206  0
         return "";
 207  
     }
 208  
 
 209  
     /**
 210  
      * This tells the system if the results are cacheable at all. Keep in mind that during forked builds and other
 211  
      * things, a given rule may be executed more than once for the same project. This means that even things that change
 212  
      * from project to project may still be cacheable in certain instances.
 213  
      */
 214  
     public boolean isCacheable()
 215  
     {
 216  0
         return false;
 217  
     }
 218  
 
 219  
     /**
 220  
      * If the rule is cacheable and the same id is found in the cache, the stored results are passed to this method to
 221  
      * allow double checking of the results. Most of the time this can be done by generating unique ids, but sometimes
 222  
      * the results of objects returned by the helper need to be queried. You may for example, store certain objects in
 223  
      * your rule and then query them later.
 224  
      */
 225  
     public boolean isResultValid( EnforcerRule arg0 )
 226  
     {
 227  0
         return false;
 228  
     }
 229  
 }