Coverage Report - org.apache.maven.plugin.idea.AbstractIdeaMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractIdeaMojo
75%
123/165
61%
55/90
4,067
 
 1  
 package org.apache.maven.plugin.idea;
 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.artifact.factory.ArtifactFactory;
 24  
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 25  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 26  
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 27  
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 28  
 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
 29  
 import org.apache.maven.artifact.resolver.ArtifactResolver;
 30  
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 31  
 import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
 32  
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 33  
 import org.apache.maven.artifact.versioning.VersionRange;
 34  
 import org.apache.maven.model.Dependency;
 35  
 import org.apache.maven.model.DependencyManagement;
 36  
 import org.apache.maven.model.Exclusion;
 37  
 import org.apache.maven.model.Plugin;
 38  
 import org.apache.maven.plugin.AbstractMojo;
 39  
 import org.apache.maven.plugin.logging.Log;
 40  
 import org.apache.maven.project.MavenProject;
 41  
 import org.apache.maven.project.ProjectBuildingException;
 42  
 import org.apache.maven.project.artifact.InvalidDependencyVersionException;
 43  
 import org.codehaus.plexus.util.StringUtils;
 44  
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 45  
 import org.dom4j.Document;
 46  
 import org.dom4j.DocumentException;
 47  
 import org.dom4j.Element;
 48  
 import org.dom4j.io.SAXReader;
 49  
 import org.dom4j.io.XMLWriter;
 50  
 
 51  
 import java.io.File;
 52  
 import java.io.IOException;
 53  
 import java.util.ArrayList;
 54  
 import java.util.Collections;
 55  
 import java.util.HashMap;
 56  
 import java.util.HashSet;
 57  
 import java.util.Iterator;
 58  
 import java.util.List;
 59  
 import java.util.Map;
 60  
 import java.util.Set;
 61  
 import java.util.StringTokenizer;
 62  
 
 63  
 /**
 64  
  * @author Edwin Punzalan
 65  
  */
 66  114
 public abstract class AbstractIdeaMojo
 67  
     extends AbstractMojo
 68  
 {
 69  
     /**
 70  
      * The Maven Project.
 71  
      *
 72  
      * @parameter expression="${executedProject}"
 73  
      * @required
 74  
      * @readonly
 75  
      */
 76  
     protected MavenProject executedProject;
 77  
 
 78  
     /* holder for the log object only */
 79  
     protected Log log;
 80  
 
 81  
     /**
 82  
      * Whether to update the existing project files or overwrite them.
 83  
      *
 84  
      * @parameter expression="${overwrite}" default-value="false"
 85  
      */
 86  
     protected boolean overwrite;
 87  
 
 88  
     /**
 89  
      * @component
 90  
      */
 91  
     protected ArtifactFactory artifactFactory;
 92  
 
 93  
     /**
 94  
      * @parameter expression="${localRepository}"
 95  
      * @required
 96  
      * @readonly
 97  
      */
 98  
     protected ArtifactRepository localRepo;
 99  
 
 100  
     /**
 101  
      * @component
 102  
      */
 103  
     protected ArtifactResolver artifactResolver;
 104  
 
 105  
     /**
 106  
      * @component role="org.apache.maven.artifact.metadata.ArtifactMetadataSource" hint="maven"
 107  
      */
 108  
     protected ArtifactMetadataSource artifactMetadataSource;
 109  
 
 110  
     public void initParam( MavenProject project, ArtifactFactory artifactFactory, ArtifactRepository localRepo,
 111  
                            ArtifactResolver artifactResolver, ArtifactMetadataSource artifactMetadataSource, Log log,
 112  
                            boolean overwrite )
 113  
     {
 114  18
         this.executedProject = project;
 115  
 
 116  18
         this.log = log;
 117  
 
 118  18
         this.artifactFactory = artifactFactory;
 119  
 
 120  18
         this.localRepo = localRepo;
 121  
 
 122  18
         this.artifactResolver = artifactResolver;
 123  
 
 124  18
         this.artifactMetadataSource = artifactMetadataSource;
 125  
 
 126  18
         this.overwrite = overwrite;
 127  18
     }
 128  
 
 129  
     protected Document readXmlDocument( File file, String altFilename )
 130  
         throws DocumentException
 131  
     {
 132  105
         SAXReader reader = new SAXReader();
 133  105
         if ( file.exists() && !overwrite )
 134  
         {
 135  105
             return reader.read( file );
 136  
         }
 137  
         else
 138  
         {
 139  0
             File altFile = new File( executedProject.getBasedir(), "src/main/idea/" + altFilename );
 140  0
             if ( altFile.exists() )
 141  
             {
 142  0
                 return reader.read( altFile );
 143  
             }
 144  
             else
 145  
             {
 146  0
                 return reader.read( getClass().getResourceAsStream( "/templates/default/" + altFilename ) );
 147  
             }
 148  
         }
 149  
     }
 150  
 
 151  
     protected void writeXmlDocument( File file, Document document )
 152  
         throws IOException
 153  
     {
 154  105
         XMLWriter writer = new IdeaXmlWriter( file );
 155  105
         writer.write( document );
 156  105
         writer.close();
 157  105
     }
 158  
 
 159  
     /**
 160  
      * Finds element from the module element.
 161  
      *
 162  
      * @param module Xpp3Dom element
 163  
      * @param name   Name attribute to find
 164  
      * @return component  Returns the Xpp3Dom element found.
 165  
      */
 166  
     protected Element findComponent( Element module, String name )
 167  
     {
 168  183
         return findElement( module, "component", name );
 169  
     }
 170  
 
 171  
     protected Element findElement( Element element, String elementName, String attributeName )
 172  
     {
 173  228
         for ( Iterator children = element.elementIterator( elementName ); children.hasNext(); )
 174  
         {
 175  1155
             Element child = (Element) children.next();
 176  1155
             if ( attributeName.equals( child.attributeValue( "name" ) ) )
 177  
             {
 178  228
                 return child;
 179  
             }
 180  
         }
 181  0
         return createElement( element, elementName ).addAttribute( "name", attributeName );
 182  
     }
 183  
 
 184  
     protected Element findElement( Element component, String name )
 185  
     {
 186  213
         Element element = component.element( name );
 187  213
         if ( element == null )
 188  
         {
 189  0
             element = createElement( component, name );
 190  
         }
 191  213
         return element;
 192  
     }
 193  
 
 194  
     /**
 195  
      * Creates an Xpp3Dom element.
 196  
      *
 197  
      * @param module Xpp3Dom element
 198  
      * @param name   Name of the element
 199  
      * @return component Xpp3Dom element
 200  
      */
 201  
     protected Element createElement( Element module, String name )
 202  
     {
 203  663
         return module.addElement( name );
 204  
     }
 205  
 
 206  
     /**
 207  
      * Translate the absolutePath into its relative path.
 208  
      *
 209  
      * @param basedir      The basedir of the project.
 210  
      * @param absolutePath The absolute path that must be translated to relative path.
 211  
      * @return relative  Relative path of the parameter absolute path.
 212  
      */
 213  
     protected String toRelative( String basedir, String absolutePath )
 214  
     {
 215  
         String relative;
 216  
 
 217  
         // Convert drive letter
 218  492
         String convertedBasedir = convertDriveLetter( basedir );
 219  492
         String convertedAbsolutePath = convertDriveLetter( absolutePath );
 220  
 
 221  
         // Normalize path separators
 222  492
         convertedBasedir = StringUtils.replace( convertedBasedir, "\\", "/" );
 223  492
         convertedAbsolutePath = StringUtils.replace( convertedAbsolutePath, "\\", "/" );
 224  
 
 225  
         // Strip trailing slash
 226  492
         if ( convertedBasedir.endsWith( "/" ) )
 227  
         {
 228  15
             convertedBasedir = convertedBasedir.substring( 0, convertedBasedir.length() - 1 );
 229  
         }
 230  492
         if ( convertedAbsolutePath.endsWith( "/" ) )
 231  
         {
 232  6
             convertedAbsolutePath = convertedAbsolutePath.substring( 0, convertedAbsolutePath.length() - 1 );
 233  
         }
 234  
 
 235  
         // IDEA-103 Make sure that the basedir is appended with a / before we attempt to match it to the absolute path
 236  492
         String matchableBasedir = convertedBasedir + "/";
 237  492
         if ( convertedAbsolutePath.startsWith( matchableBasedir )
 238  
             && convertedAbsolutePath.length() > matchableBasedir.length() )
 239  
         {
 240  
             // Simple case, path starts with basepath
 241  438
             relative = convertedAbsolutePath.substring( matchableBasedir.length() );
 242  
         }
 243  
         else
 244  
         {
 245  
             // It's more complex...
 246  54
             StringTokenizer baseTokens = new StringTokenizer( convertedBasedir, "/", false );
 247  
 
 248  54
             int baseCount = baseTokens.countTokens();
 249  54
             List baseTokenList = new ArrayList( baseCount );
 250  462
             while ( baseTokens.hasMoreTokens() )
 251  
             {
 252  408
                 baseTokenList.add( baseTokens.nextToken() );
 253  
             }
 254  
 
 255  54
             StringTokenizer pathTokens = new StringTokenizer( convertedAbsolutePath, "/", false );
 256  
 
 257  54
             int pathCount = pathTokens.countTokens();
 258  54
             List pathTokenList = new ArrayList( pathCount );
 259  258
             while ( pathTokens.hasMoreTokens() )
 260  
             {
 261  204
                 pathTokenList.add( pathTokens.nextToken() );
 262  
             }
 263  
 
 264  54
             int maxCount = Math.max( baseTokenList.size(), pathTokenList.size() );
 265  54
             int differIndex = -1;
 266  84
             for ( int i = 0; i < maxCount; i++ )
 267  
             {
 268  84
                 if ( i >= pathTokenList.size() || i >= baseTokenList.size() )
 269  
                 {
 270  0
                     differIndex = i;
 271  0
                     break;
 272  
                 }
 273  84
                 String basePart = (String) baseTokenList.get( i );
 274  84
                 String pathPart = (String) pathTokenList.get( i );
 275  84
                 if ( !basePart.equals( pathPart ) )
 276  
                 {
 277  54
                     differIndex = i;
 278  54
                     break;
 279  
                 }
 280  
             }
 281  54
             if ( getLog().isDebugEnabled() )
 282  
             {
 283  0
                 getLog().debug( "Construction of relative path... differIndex=" + differIndex );
 284  
             }
 285  54
             if ( differIndex < 1 )
 286  
             {
 287  
                 // Paths are either equal or completely different
 288  36
                 relative = convertedAbsolutePath;
 289  
             }
 290  
             else
 291  
             {
 292  18
                 StringBuffer result = new StringBuffer();
 293  18
                 int parentCount = baseTokenList.size() - differIndex;
 294  18
                 if ( getLog().isDebugEnabled() )
 295  
                 {
 296  0
                     getLog().debug( "parentCount=" + parentCount );
 297  
                 }
 298  18
                 boolean isFirst = true;
 299  36
                 for ( int i = 0; i < parentCount; i++ )
 300  
                 {
 301  
                     // Add parents
 302  18
                     if ( isFirst )
 303  
                     {
 304  18
                         isFirst = false;
 305  
                     }
 306  
                     else
 307  
                     {
 308  0
                         result.append( "/" );
 309  
                     }
 310  18
                     result.append( ".." );
 311  
                 }
 312  42
                 for ( int i = differIndex; i < pathTokenList.size(); i++ )
 313  
                 {
 314  
                     // Add the remaining path elements
 315  24
                     if ( isFirst )
 316  
                     {
 317  0
                         isFirst = false;
 318  
                     }
 319  
                     else
 320  
                     {
 321  24
                         result.append( "/" );
 322  
                     }
 323  24
                     result.append( pathTokenList.get( i ) );
 324  
                 }
 325  18
                 relative = result.toString();
 326  
             }
 327  
         }
 328  
 
 329  492
         if ( getLog().isDebugEnabled() )
 330  
         {
 331  0
             getLog().debug( "toRelative(" + basedir + ", " + absolutePath + ") => " + relative );
 332  
         }
 333  
 
 334  492
         return relative;
 335  
     }
 336  
 
 337  
     /**
 338  
      * Convert the drive letter, if there is one, to upper case. This is done
 339  
      * to avoid case mismatch when running cygwin on Windows.
 340  
      *
 341  
      * @param absolutePath The path to convert
 342  
      * @return The path that came in with its drive letter converted to upper case
 343  
      */
 344  
     String convertDriveLetter( String absolutePath )
 345  
     {
 346  1230
         if ( absolutePath != null && absolutePath.length() >= 3 && !absolutePath.startsWith( "/" ) )
 347  
         {
 348  
             // See if the path starts with "?:\", where ? must be a letter
 349  1218
             if ( Character.isLetter( absolutePath.substring( 0, 1 ).charAt( 0 ) )
 350  
                 && absolutePath.substring( 1, 3 ).equals( ":\\" ) )
 351  
             {
 352  
                 // In that case we convert the first character to upper case
 353  1164
                 return absolutePath.substring( 0, 1 ).toUpperCase() + absolutePath.substring( 1 );
 354  
             }
 355  
         }
 356  66
         return absolutePath;
 357  
     }
 358  
 
 359  
     /**
 360  
      * Remove elements from content (Xpp3Dom).
 361  
      *
 362  
      * @param content Xpp3Dom element
 363  
      * @param name    Name of the element to be removed
 364  
      */
 365  
     protected void removeOldElements( Element content, String name )
 366  
     {
 367  291
         for ( Iterator children = content.elementIterator(); children.hasNext(); )
 368  
         {
 369  618
             Element child = (Element) children.next();
 370  618
             if ( name.equals( child.getName() ) )
 371  
             {
 372  390
                 content.remove( child );
 373  
             }
 374  
         }
 375  291
     }
 376  
 
 377  
     protected void doDependencyResolution( MavenProject project, ArtifactRepository localRepo )
 378  
         throws InvalidDependencyVersionException, ProjectBuildingException, InvalidVersionSpecificationException
 379  
     {
 380  93
         Map managedVersions =
 381  
             createManagedVersionMap( artifactFactory, project.getId(), project.getDependencyManagement() );
 382  
 
 383  
         try
 384  
         {
 385  93
             ArtifactResolutionResult result = artifactResolver.resolveTransitively( getProjectArtifacts(),
 386  
                                                                                     project.getArtifact(),
 387  
                                                                                     managedVersions, localRepo,
 388  
                                                                                     project.getRemoteArtifactRepositories(),
 389  
                                                                                     artifactMetadataSource );
 390  
 
 391  87
             project.setArtifacts( result.getArtifacts() );
 392  
         }
 393  0
         catch ( ArtifactNotFoundException e )
 394  
         {
 395  0
             getLog().debug( e.getMessage(), e );
 396  
 
 397  0
             StringBuffer msg = new StringBuffer();
 398  0
             msg.append( "An error occurred during dependency resolution.\n\n" );
 399  0
             msg.append( "    Failed to retrieve " + e.getDownloadUrl() + "\n" );
 400  0
             msg.append( "from the following repositories:" );
 401  0
             for ( Iterator repositories = e.getRemoteRepositories().iterator(); repositories.hasNext(); )
 402  
             {
 403  0
                 ArtifactRepository repository = (ArtifactRepository) repositories.next();
 404  0
                 msg.append( "\n    " + repository.getId() + "(" + repository.getUrl() + ")" );
 405  
             }
 406  0
             msg.append( "\nCaused by: " + e.getMessage() );
 407  
 
 408  0
             getLog().warn( msg );
 409  
         }
 410  6
         catch ( ArtifactResolutionException e )
 411  
         {
 412  6
             getLog().debug( e.getMessage(), e );
 413  
 
 414  6
             StringBuffer msg = new StringBuffer();
 415  6
             msg.append( "An error occurred during dependency resolution of the following artifact:\n\n" );
 416  6
             msg.append( "    " + e.getGroupId() + ":" + e.getArtifactId() + e.getVersion() + "\n\n" );
 417  6
             msg.append( "Caused by: " + e.getMessage() );
 418  
 
 419  6
             getLog().warn( msg );
 420  87
         }
 421  93
     }
 422  
 
 423  
     /*
 424  
     * @todo we need a more permanent feature that does this properly
 425  
     */
 426  
     protected String getPluginSetting( String artifactId, String optionName, String defaultValue )
 427  
     {
 428  21
         for ( Iterator it = executedProject.getBuildPlugins().iterator(); it.hasNext(); )
 429  
         {
 430  0
             Plugin plugin = (Plugin) it.next();
 431  0
             if ( plugin.getArtifactId().equals( artifactId ) )
 432  
             {
 433  0
                 Xpp3Dom o = (Xpp3Dom) plugin.getConfiguration();
 434  0
                 if ( o != null && o.getChild( optionName ) != null )
 435  
                 {
 436  0
                     return o.getChild( optionName ).getValue();
 437  
                 }
 438  
             }
 439  
         }
 440  21
         return defaultValue;
 441  
     }
 442  
 
 443  
     private Set getProjectArtifacts()
 444  
         throws InvalidVersionSpecificationException
 445  
     {
 446  93
         Set artifacts = new HashSet();
 447  
 
 448  93
         for ( Iterator dependencies = executedProject.getDependencies().iterator(); dependencies.hasNext(); )
 449  
         {
 450  189
             Dependency dep = (Dependency) dependencies.next();
 451  
 
 452  189
             String groupId = dep.getGroupId();
 453  189
             String artifactId = dep.getArtifactId();
 454  189
             VersionRange versionRange = VersionRange.createFromVersionSpec( dep.getVersion() );
 455  189
             String type = dep.getType();
 456  189
             if ( type == null )
 457  
             {
 458  0
                 type = "jar";
 459  
             }
 460  189
             String classifier = dep.getClassifier();
 461  189
             boolean optional = dep.isOptional();
 462  189
             String scope = dep.getScope();
 463  189
             if ( scope == null )
 464  
             {
 465  0
                 scope = Artifact.SCOPE_COMPILE;
 466  
             }
 467  
 
 468  189
             Artifact artifact = artifactFactory.createDependencyArtifact( groupId, artifactId, versionRange, type,
 469  
                                                                           classifier, scope, optional );
 470  
 
 471  189
             if ( scope.equalsIgnoreCase( Artifact.SCOPE_SYSTEM ) )
 472  
             {
 473  6
                 artifact.setFile( new File( dep.getSystemPath() ) );
 474  
             }
 475  
 
 476  189
             List exclusions = new ArrayList();
 477  189
             for ( Iterator j = dep.getExclusions().iterator(); j.hasNext(); )
 478  
             {
 479  0
                 Exclusion e = (Exclusion) j.next();
 480  0
                 exclusions.add( e.getGroupId() + ":" + e.getArtifactId() );
 481  
             }
 482  
 
 483  189
             ArtifactFilter newFilter = new ExcludesArtifactFilter( exclusions );
 484  
 
 485  189
             artifact.setDependencyFilter( newFilter );
 486  
 
 487  189
             artifacts.add( artifact );
 488  
         }
 489  
 
 490  93
         return artifacts;
 491  
     }
 492  
 
 493  
     private Map createManagedVersionMap( ArtifactFactory artifactFactory, String projectId,
 494  
                                          DependencyManagement dependencyManagement )
 495  
         throws ProjectBuildingException
 496  
     {
 497  
         Map map;
 498  93
         if ( dependencyManagement != null && dependencyManagement.getDependencies() != null )
 499  
         {
 500  0
             map = new HashMap();
 501  0
             for ( Iterator i = dependencyManagement.getDependencies().iterator(); i.hasNext(); )
 502  
             {
 503  0
                 Dependency d = (Dependency) i.next();
 504  
 
 505  
                 try
 506  
                 {
 507  0
                     VersionRange versionRange = VersionRange.createFromVersionSpec( d.getVersion() );
 508  0
                     Artifact artifact = artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(),
 509  
                                                                                   versionRange, d.getType(),
 510  
                                                                                   d.getClassifier(), d.getScope(),
 511  
                                                                                   d.isOptional() );
 512  0
                     map.put( d.getManagementKey(), artifact );
 513  
                 }
 514  0
                 catch ( InvalidVersionSpecificationException e )
 515  
                 {
 516  0
                     throw new ProjectBuildingException( projectId, "Unable to parse version '" + d.getVersion()
 517  
                         + "' for dependency '" + d.getManagementKey() + "': " + e.getMessage(), e );
 518  0
                 }
 519  
             }
 520  
         }
 521  
         else
 522  
         {
 523  93
             map = Collections.EMPTY_MAP;
 524  
         }
 525  93
         return map;
 526  
     }
 527  
 
 528  
     public Log getLog()
 529  
     {
 530  633
         if ( log == null )
 531  
         {
 532  69
             log = super.getLog();
 533  
         }
 534  
 
 535  633
         return log;
 536  
     }
 537  
 }