Coverage Report - org.apache.maven.plugin.idea.IdeaModuleMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
IdeaModuleMojo
89%
344/387
78%
151/194
5,182
 
 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.manager.WagonManager;
 25  
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 26  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 27  
 import org.apache.maven.artifact.resolver.ArtifactResolver;
 28  
 import org.apache.maven.model.Resource;
 29  
 import org.apache.maven.plugin.MojoExecutionException;
 30  
 import org.apache.maven.plugin.logging.Log;
 31  
 import org.apache.maven.project.MavenProject;
 32  
 import org.apache.maven.wagon.ResourceDoesNotExistException;
 33  
 import org.apache.maven.wagon.TransferFailedException;
 34  
 import org.codehaus.plexus.util.StringUtils;
 35  
 import org.dom4j.Document;
 36  
 import org.dom4j.DocumentException;
 37  
 import org.dom4j.Element;
 38  
 
 39  
 import java.io.File;
 40  
 import java.io.IOException;
 41  
 import java.util.ArrayList;
 42  
 import java.util.Collections;
 43  
 import java.util.HashMap;
 44  
 import java.util.HashSet;
 45  
 import java.util.Iterator;
 46  
 import java.util.List;
 47  
 import java.util.Map;
 48  
 import java.util.Set;
 49  
 import java.util.regex.Matcher;
 50  
 import java.util.regex.Pattern;
 51  
 
 52  
 /**
 53  
  * Creates the module files (*.iml) for IntelliJ IDEA.
 54  
  *
 55  
  * @author Edwin Punzalan
 56  
  * @goal module
 57  
  * @execute phase="generate-sources"
 58  
  */
 59  34
 public class IdeaModuleMojo
 60  
     extends AbstractIdeaMojo
 61  
 {
 62  
     /**
 63  
      * The reactor projects in a multi-module build.
 64  
      *
 65  
      * @parameter expression="${reactorProjects}"
 66  
      * @required
 67  
      * @readonly
 68  
      */
 69  
     private List reactorProjects;
 70  
 
 71  
     /**
 72  
      * @component
 73  
      */
 74  
     private WagonManager wagonManager;
 75  
 
 76  
     /**
 77  
      * Whether to link the reactor projects as dependency modules or as libraries.
 78  
      *
 79  
      * @parameter expression="${linkModules}" default-value="true"
 80  
      */
 81  
     private boolean linkModules;
 82  
 
 83  
     /**
 84  
      * Specify the location of the deployment descriptor file, if one is provided.
 85  
      *
 86  
      * @parameter expression="${deploymentDescriptorFile}"
 87  
      */
 88  
     private String deploymentDescriptorFile;
 89  
 
 90  
     /**
 91  
      * Whether to use full artifact names when referencing libraries.
 92  
      *
 93  
      * @parameter expression="${useFullNames}" default-value="false"
 94  
      */
 95  
     private boolean useFullNames;
 96  
 
 97  
     /**
 98  
      * Enables/disables the downloading of source attachments.
 99  
      *
 100  
      * @parameter expression="${downloadSources}" default-value="false"
 101  
      */
 102  
     private boolean downloadSources;
 103  
 
 104  
     /**
 105  
      * Enables/disables the downloading of javadoc attachments.
 106  
      *
 107  
      * @parameter expression="${downloadJavadocs}" default-value="false"
 108  
      */
 109  
     private boolean downloadJavadocs;
 110  
 
 111  
     /**
 112  
      * Sets the classifier string attached to an artifact source archive name.
 113  
      *
 114  
      * @parameter expression="${sourceClassifier}" default-value="sources"
 115  
      */
 116  
     private String sourceClassifier;
 117  
 
 118  
     /**
 119  
      * Sets the classifier string attached to an artifact javadoc archive name.
 120  
      *
 121  
      * @parameter expression="${javadocClassifier}" default-value="javadoc"
 122  
      */
 123  
     private String javadocClassifier;
 124  
 
 125  
     /**
 126  
      * An optional set of Library objects that allow you to specify a comma separated list of source dirs, class dirs,
 127  
      * or to indicate that the library should be excluded from the module. For example:
 128  
      * <p/>
 129  
      * <pre>
 130  
      * &lt;libraries&gt;
 131  
      *  &lt;library&gt;
 132  
      *      &lt;name&gt;webwork&lt;/name&gt;
 133  
      *      &lt;sources&gt;file://$webwork$/src/java&lt;/sources&gt;
 134  
      *      &lt;!--
 135  
      *      &lt;classes&gt;...&lt;/classes&gt;
 136  
      *      &lt;exclude&gt;true&lt;/exclude&gt;
 137  
      *      --&gt;
 138  
      *  &lt;/library&gt;
 139  
      * &lt;/libraries&gt;
 140  
      * </pre>
 141  
      *
 142  
      * @parameter
 143  
      */
 144  
     private Library[] libraries;
 145  
 
 146  
     /**
 147  
      * A comma-separated list of directories that should be excluded. These directories are in addition to those
 148  
      * already excluded, such as target.
 149  
      *
 150  
      * @parameter
 151  
      */
 152  
     private String exclude;
 153  
 
 154  
     /**
 155  
      * Causes the module libraries to use a short name for all dependencies. This is very convenient but has been
 156  
      * reported to cause problems with IDEA.
 157  
      *
 158  
      * @parameter default-value="false"
 159  
      */
 160  
     private boolean dependenciesAsLibraries;
 161  
 
 162  
     /**
 163  
      * A temporary cache of artifacts that's already been downloaded or
 164  
      * attempted to be downloaded. This is to refrain from trying to download a
 165  
      * dependency that we have already tried to download.
 166  
      *
 167  
      * @todo this is nasty! the only reason this is static is to use the same cache between reactor calls
 168  
      */
 169  2
     private static Map attemptedDownloads = new HashMap();
 170  
 
 171  
     /**
 172  
      * Tell IntelliJ IDEA that this module is an IntelliJ IDEA Plugin.
 173  
      *
 174  
      * @parameter default-value="false"
 175  
      */
 176  
     private boolean ideaPlugin;
 177  
 
 178  
     /**
 179  
      * Specify the version of IDEA to target.  This is needed to identify the default formatting of
 180  
      * project-jdk-name used by IDEA.  Currently supports 4.x and 5.x.
 181  
      * <p/>
 182  
      * This will only be used when parameter jdkName is not set.
 183  
      *
 184  
      * @parameter expression="${ideaVersion}" default-value="5.x"
 185  
      */
 186  
     private String ideaVersion;
 187  
 
 188  
     private Set macros;
 189  
 
 190  
     public void initParam( MavenProject project, ArtifactFactory artifactFactory, ArtifactRepository localRepo,
 191  
                            ArtifactResolver artifactResolver, ArtifactMetadataSource artifactMetadataSource, Log log,
 192  
                            boolean overwrite, MavenProject executedProject, List reactorProjects,
 193  
                            WagonManager wagonManager, boolean linkModules, boolean useFullNames,
 194  
                            boolean downloadSources, String sourceClassifier, boolean downloadJavadocs,
 195  
                            String javadocClassifier, Library[] libraries, Set macros, String exclude,
 196  
                            boolean useShortDependencyNames, String deploymentDescriptorFile, boolean ideaPlugin,
 197  
                            String ideaVersion )
 198  
     {
 199  4
         super.initParam( project, artifactFactory, localRepo, artifactResolver, artifactMetadataSource, log,
 200  
                          overwrite );
 201  
 
 202  4
         this.reactorProjects = reactorProjects;
 203  
 
 204  4
         this.wagonManager = wagonManager;
 205  
 
 206  4
         this.linkModules = linkModules;
 207  
 
 208  4
         this.useFullNames = useFullNames;
 209  
 
 210  4
         this.downloadSources = downloadSources;
 211  
 
 212  4
         this.sourceClassifier = sourceClassifier;
 213  
 
 214  4
         this.downloadJavadocs = downloadJavadocs;
 215  
 
 216  4
         this.javadocClassifier = javadocClassifier;
 217  
 
 218  4
         this.libraries = libraries;
 219  
 
 220  4
         this.macros = macros;
 221  
 
 222  4
         this.exclude = exclude;
 223  
 
 224  4
         this.dependenciesAsLibraries = useShortDependencyNames;
 225  
 
 226  4
         this.deploymentDescriptorFile = deploymentDescriptorFile;
 227  
 
 228  4
         this.ideaPlugin = ideaPlugin;
 229  
 
 230  4
         this.ideaVersion = ideaVersion;
 231  4
     }
 232  
 
 233  
     /**
 234  
      * Create IDEA (.iml) project files.
 235  
      *
 236  
      * @throws org.apache.maven.plugin.MojoExecutionException
 237  
      *
 238  
      */
 239  
     public void execute()
 240  
         throws MojoExecutionException
 241  
     {
 242  
         try
 243  
         {
 244  30
             doDependencyResolution( executedProject, localRepo );
 245  
         }
 246  0
         catch ( Exception e )
 247  
         {
 248  0
             throw new MojoExecutionException( "Unable to build project dependencies.", e );
 249  30
         }
 250  
 
 251  30
         rewriteModule();
 252  30
     }
 253  
 
 254  
     public void rewriteModule()
 255  
         throws MojoExecutionException
 256  
     {
 257  34
         File moduleFile = new File( executedProject.getBasedir(), executedProject.getArtifactId() + ".iml" );
 258  
         try
 259  
         {
 260  34
             Document document = readXmlDocument( moduleFile, "module.xml" );
 261  
 
 262  34
             Element module = document.getRootElement();
 263  
 
 264  
             // TODO: how can we let the WAR/EJBs plugin hook in and provide this?
 265  
             // TODO: merge in ejb-module, etc.
 266  34
             if ( "war".equals( executedProject.getPackaging() ) )
 267  
             {
 268  10
                 addWebModule( module );
 269  
             }
 270  24
             else if ( "ejb".equals( executedProject.getPackaging() ) )
 271  
             {
 272  4
                 addEjbModule( module );
 273  
             }
 274  20
             else if ( "ear".equals( executedProject.getPackaging() ) )
 275  
             {
 276  2
                 addEarModule( module );
 277  
             }
 278  18
             else if ( ideaPlugin )
 279  
             {
 280  0
                 addPluginModule( module );
 281  
             }
 282  
 
 283  34
             Element component = findComponent( module, "NewModuleRootManager" );
 284  34
             Element output = findElement( component, "output" );
 285  34
             output.addAttribute( "url", getModuleFileUrl( executedProject.getBuild().getOutputDirectory() ) );
 286  
 
 287  34
             Element outputTest = findElement( component, "output-test" );
 288  34
             outputTest.addAttribute( "url", getModuleFileUrl( executedProject.getBuild().getTestOutputDirectory() ) );
 289  
 
 290  34
             Element content = findElement( component, "content" );
 291  
 
 292  34
             removeOldElements( content, "sourceFolder" );
 293  
 
 294  34
             for ( Iterator i = executedProject.getCompileSourceRoots().iterator(); i.hasNext(); )
 295  
             {
 296  34
                 String directory = (String) i.next();
 297  34
                 addSourceFolder( content, directory, false );
 298  
             }
 299  34
             for ( Iterator i = executedProject.getTestCompileSourceRoots().iterator(); i.hasNext(); )
 300  
             {
 301  34
                 String directory = (String) i.next();
 302  34
                 addSourceFolder( content, directory, true );
 303  
             }
 304  
 
 305  34
             for ( Iterator i = executedProject.getBuild().getResources().iterator(); i.hasNext(); )
 306  
             {
 307  34
                 Resource resource = (Resource) i.next();
 308  34
                 String directory = resource.getDirectory();
 309  34
                 if ( resource.getTargetPath() == null && !resource.isFiltering() )
 310  
                 {
 311  34
                     addSourceFolder( content, directory, false );
 312  
                 }
 313  
                 else
 314  
                 {
 315  0
                     getLog().info(
 316  
                         "Not adding resource directory as it has an incompatible target path or filtering: "
 317  
                             + directory );
 318  
                 }
 319  
             }
 320  
 
 321  34
             for ( Iterator i = executedProject.getBuild().getTestResources().iterator(); i.hasNext(); )
 322  
             {
 323  34
                 Resource resource = (Resource) i.next();
 324  34
                 String directory = resource.getDirectory();
 325  34
                 if ( resource.getTargetPath() == null && !resource.isFiltering() )
 326  
                 {
 327  34
                     addSourceFolder( content, directory, true );
 328  
                 }
 329  
                 else
 330  
                 {
 331  0
                     getLog().info(
 332  
                         "Not adding test resource directory as it has an incompatible target path or filtering: "
 333  
                             + directory );
 334  
                 }
 335  
             }
 336  
 
 337  34
             removeOldElements( content, "excludeFolder" );
 338  
 
 339  
             //For excludeFolder
 340  34
             File target = new File( executedProject.getBuild().getDirectory() );
 341  34
             File classes = new File( executedProject.getBuild().getOutputDirectory() );
 342  34
             File testClasses = new File( executedProject.getBuild().getTestOutputDirectory() );
 343  
 
 344  34
             List sourceFolders = content.elements( "sourceFolder" );
 345  
 
 346  34
             List filteredExcludes = new ArrayList();
 347  34
             filteredExcludes.addAll( getExcludedDirectories( target, filteredExcludes, sourceFolders ) );
 348  34
             filteredExcludes.addAll( getExcludedDirectories( classes, filteredExcludes, sourceFolders ) );
 349  34
             filteredExcludes.addAll( getExcludedDirectories( testClasses, filteredExcludes, sourceFolders ) );
 350  
 
 351  34
             if ( exclude != null )
 352  
             {
 353  4
                 String[] dirs = exclude.split( "[,\\s]+" );
 354  12
                 for ( int i = 0; i < dirs.length; i++ )
 355  
                 {
 356  8
                     File excludedDir = new File( executedProject.getBasedir(), dirs[i] );
 357  8
                     filteredExcludes.addAll( getExcludedDirectories( excludedDir, filteredExcludes, sourceFolders ) );
 358  
                 }
 359  
             }
 360  
 
 361  
             // even though we just ran all the directories in the filteredExcludes List through the intelligent
 362  
             // getExcludedDirectories method, we never actually were guaranteed the order that they were added was
 363  
             // in the order required to make the most optimized exclude list. In addition, the smart logic from
 364  
             // that method is entirely skipped if the directory doesn't currently exist. A simple string matching
 365  
             // will do pretty much the same thing and make the list more concise.
 366  34
             ArrayList actuallyExcluded = new ArrayList();
 367  34
             Collections.sort( filteredExcludes );
 368  34
             for ( Iterator i = filteredExcludes.iterator(); i.hasNext(); )
 369  
             {
 370  110
                 String dirToExclude = i.next().toString();
 371  110
                 String dirToExcludeTemp = dirToExclude.replace( '\\', '/' );
 372  110
                 boolean addExclude = true;
 373  110
                 for ( Iterator iterator = actuallyExcluded.iterator(); iterator.hasNext(); )
 374  
                 {
 375  90
                     String dir = iterator.next().toString();
 376  90
                     String dirTemp = dir.replace( '\\', '/' );
 377  90
                     if ( dirToExcludeTemp.startsWith( dirTemp + "/" ) )
 378  
                     {
 379  70
                         addExclude = false;
 380  70
                         break;
 381  
                     }
 382  20
                     else if ( dir.startsWith( dirToExcludeTemp + "/" ) )
 383  
                     {
 384  0
                         actuallyExcluded.remove( dir );
 385  
                     }
 386  
                 }
 387  
 
 388  110
                 if ( addExclude )
 389  
                 {
 390  40
                     actuallyExcluded.add( dirToExclude );
 391  40
                     addExcludeFolder( content, dirToExclude );
 392  
                 }
 393  
             }
 394  
 
 395  
             //Remove default exclusion for output dirs if there are sources in it
 396  34
             String outputModuleUrl = getModuleFileUrl( executedProject.getBuild().getOutputDirectory() );
 397  34
             String testOutputModuleUrl = getModuleFileUrl( executedProject.getBuild().getTestOutputDirectory() );
 398  34
             for ( Iterator i = content.elements( "sourceFolder" ).iterator(); i.hasNext(); )
 399  
             {
 400  68
                 Element sourceFolder = (Element) i.next();
 401  68
                 String sourceUrl = sourceFolder.attributeValue( "url" ).replace( '\\', '/' );
 402  68
                 if ( sourceUrl.startsWith( outputModuleUrl + "/" ) || sourceUrl.startsWith( testOutputModuleUrl ) )
 403  
                 {
 404  0
                     component.remove( component.element( "exclude-output" ) );
 405  0
                     break;
 406  
                 }
 407  
             }
 408  
 
 409  34
             rewriteDependencies( component );
 410  
 
 411  34
             writeXmlDocument( moduleFile, document );
 412  
         }
 413  0
         catch ( DocumentException e )
 414  
         {
 415  0
             throw new MojoExecutionException( "Error parsing existing IML file " + moduleFile.getAbsolutePath(), e );
 416  
         }
 417  0
         catch ( IOException e )
 418  
         {
 419  0
             throw new MojoExecutionException( "Error parsing existing IML file " + moduleFile.getAbsolutePath(), e );
 420  34
         }
 421  34
     }
 422  
 
 423  
     private void rewriteDependencies( Element component )
 424  
     {
 425  34
         Map modulesByName = new HashMap();
 426  34
         Map modulesByUrl = new HashMap();
 427  34
         Set unusedModules = new HashSet();
 428  34
         for ( Iterator children = component.elementIterator( "orderEntry" ); children.hasNext(); )
 429  
         {
 430  146
             Element orderEntry = (Element) children.next();
 431  
 
 432  146
             String type = orderEntry.attributeValue( "type" );
 433  146
             if ( "module".equals( type ) )
 434  
             {
 435  6
                 modulesByName.put( orderEntry.attributeValue( "module-name" ), orderEntry );
 436  
             }
 437  140
             else if ( "module-library".equals( type ) )
 438  
             {
 439  
                 // keep track for later so we know what is left
 440  72
                 unusedModules.add( orderEntry );
 441  
 
 442  72
                 Element lib = orderEntry.element( "library" );
 443  72
                 String name = lib.attributeValue( "name" );
 444  72
                 if ( name != null )
 445  
                 {
 446  8
                     modulesByName.put( name, orderEntry );
 447  
                 }
 448  
                 else
 449  
                 {
 450  64
                     Element classesChild = lib.element( "CLASSES" );
 451  64
                     if ( classesChild != null )
 452  
                     {
 453  64
                         Element rootChild = classesChild.element( "root" );
 454  64
                         if ( rootChild != null )
 455  
                         {
 456  64
                             String url = rootChild.attributeValue( "url" );
 457  64
                             if ( url != null )
 458  
                             {
 459  
                                 // Need to ignore case because of Windows drive letters
 460  64
                                 modulesByUrl.put( url.toLowerCase(), orderEntry );
 461  
                             }
 462  
                         }
 463  
                     }
 464  
                 }
 465  
             }
 466  
         }
 467  
 
 468  34
         List testClasspathElements = executedProject.getTestArtifacts();
 469  34
         for ( Iterator i = testClasspathElements.iterator(); i.hasNext(); )
 470  
         {
 471  80
             Artifact a = (Artifact) i.next();
 472  
 
 473  80
             Library library = findLibrary( a );
 474  80
             if ( library != null && library.isExclude() )
 475  
             {
 476  2
                 continue;
 477  
             }
 478  
 
 479  
             String moduleName;
 480  78
             if ( useFullNames )
 481  
             {
 482  4
                 moduleName = a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getType() + ':' + a.getVersion();
 483  
             }
 484  
             else
 485  
             {
 486  74
                 moduleName = a.getArtifactId();
 487  
             }
 488  
 
 489  78
             Element dep = (Element) modulesByName.get( moduleName );
 490  
 
 491  78
             if ( dep == null )
 492  
             {
 493  
                 // Need to ignore case because of Windows drive letters
 494  64
                 dep = (Element) modulesByUrl.get( getLibraryUrl( a ).toLowerCase() );
 495  
             }
 496  
 
 497  78
             if ( dep != null )
 498  
             {
 499  78
                 unusedModules.remove( dep );
 500  
             }
 501  
             else
 502  
             {
 503  0
                 dep = createElement( component, "orderEntry" );
 504  
             }
 505  
 
 506  78
             boolean isIdeaModule = false;
 507  78
             if ( linkModules )
 508  
             {
 509  78
                 isIdeaModule = isReactorProject( a.getGroupId(), a.getArtifactId() );
 510  
 
 511  78
                 if ( isIdeaModule )
 512  
                 {
 513  6
                     dep.addAttribute( "type", "module" );
 514  6
                     dep.addAttribute( "module-name", moduleName );
 515  
                 }
 516  
             }
 517  
 
 518  78
             if ( a.getFile() != null && !isIdeaModule )
 519  
             {
 520  72
                 dep.addAttribute( "type", "module-library" );
 521  
 
 522  72
                 Element lib = dep.element( "library" );
 523  
 
 524  72
                 if ( lib == null )
 525  
                 {
 526  0
                     lib = createElement( dep, "library" );
 527  
                 }
 528  
 
 529  72
                 if ( dependenciesAsLibraries )
 530  
                 {
 531  4
                     lib.addAttribute( "name", moduleName );
 532  
                 }
 533  
 
 534  
                 // replace classes
 535  72
                 removeOldElements( lib, "CLASSES" );
 536  72
                 Element classes = createElement( lib, "CLASSES" );
 537  72
                 if ( library != null && library.getSplitClasses().length > 0 )
 538  
                 {
 539  4
                     lib.addAttribute( "name", moduleName );
 540  4
                     String[] libraryClasses = library.getSplitClasses();
 541  8
                     for ( int k = 0; k < libraryClasses.length; k++ )
 542  
                     {
 543  4
                         String classpath = libraryClasses[k];
 544  4
                         extractMacro( classpath );
 545  4
                         Element classEl = createElement( classes, "root" );
 546  4
                         classEl.addAttribute( "url", classpath );
 547  
                     }
 548  
                 }
 549  
                 else
 550  
                 {
 551  68
                     createElement( classes, "root" ).addAttribute( "url", getLibraryUrl( a ) );
 552  
                 }
 553  
 
 554  72
                 if ( library != null && library.getSplitSources().length > 0 )
 555  
                 {
 556  4
                     removeOldElements( lib, "SOURCES" );
 557  4
                     Element sourcesElement = createElement( lib, "SOURCES" );
 558  4
                     String[] sources = library.getSplitSources();
 559  8
                     for ( int k = 0; k < sources.length; k++ )
 560  
                     {
 561  4
                         String source = sources[k];
 562  4
                         extractMacro( source );
 563  4
                         Element sourceEl = createElement( sourcesElement, "root" );
 564  4
                         sourceEl.addAttribute( "url", source );
 565  
                     }
 566  
                 }
 567  68
                 else if ( downloadSources )
 568  
                 {
 569  4
                     resolveClassifier( createOrGetElement( lib, "SOURCES" ), a, sourceClassifier );
 570  
                 }
 571  
 
 572  72
                 if ( library != null && library.getSplitJavadocs().length > 0 )
 573  
                 {
 574  0
                     removeOldElements( lib, "JAVADOC" );
 575  0
                     Element javadocsElement = createElement( lib, "JAVADOC" );
 576  0
                     String[] javadocs = library.getSplitJavadocs();
 577  0
                     for ( int k = 0; k < javadocs.length; k++ )
 578  
                     {
 579  0
                         String javadoc = javadocs[k];
 580  0
                         extractMacro( javadoc );
 581  0
                         Element sourceEl = createElement( javadocsElement, "root" );
 582  0
                         sourceEl.addAttribute( "url", javadoc );
 583  
                     }
 584  
                 }
 585  72
                 else if ( downloadJavadocs )
 586  
                 {
 587  4
                     resolveClassifier( createOrGetElement( lib, "JAVADOC" ), a, javadocClassifier );
 588  
                 }
 589  
             }
 590  
         }
 591  
 
 592  34
         for ( Iterator i = unusedModules.iterator(); i.hasNext(); )
 593  
         {
 594  0
             Element orderEntry = (Element) i.next();
 595  
 
 596  0
             component.remove( orderEntry );
 597  
         }
 598  34
     }
 599  
 
 600  
     private Element createOrGetElement( Element lib, String name )
 601  
     {
 602  8
         Element el = lib.element( name );
 603  
 
 604  8
         if ( el == null )
 605  
         {
 606  0
             el = createElement( lib, name );
 607  
         }
 608  8
         return el;
 609  
     }
 610  
 
 611  
     private void addEarModule( Element module )
 612  
     {
 613  2
         module.addAttribute( "type", "J2EE_APPLICATION_MODULE" );
 614  2
         Element component = findComponent( module, "ApplicationModuleProperties" );
 615  2
         addDeploymentDescriptor( component, "application.xml", "1.3",
 616  
                                  executedProject.getBuild().getDirectory() + "/application.xml" );
 617  2
     }
 618  
 
 619  
     private void addEjbModule( Element module )
 620  
     {
 621  4
         String ejbVersion = getPluginSetting( "maven-ejb-plugin", "ejbVersion", "2.x" );
 622  
 
 623  4
         module.addAttribute( "type", "J2EE_EJB_MODULE" );
 624  
 
 625  4
         String explodedDir = executedProject.getBuild().getDirectory() + "/" + executedProject.getArtifactId();
 626  
 
 627  4
         Element component = findComponent( module, "EjbModuleBuildComponent" );
 628  
 
 629  4
         Element setting = findSetting( component, "EXPLODED_URL" );
 630  4
         setting.addAttribute( "value", getModuleFileUrl( explodedDir ) );
 631  
 
 632  4
         component = findComponent( module, "EjbModuleProperties" );
 633  4
         Element deployDescElement =
 634  
             addDeploymentDescriptor( component, "ejb-jar.xml", ejbVersion, "src/main/resources/META-INF/ejb-jar.xml" );
 635  4
         deployDescElement.addAttribute( "optional", ejbVersion.startsWith( "3" ) + "" );
 636  
 
 637  4
         removeOldElements( component, "containerElement" );
 638  4
         List artifacts = executedProject.getTestArtifacts();
 639  4
         for ( Iterator i = artifacts.iterator(); i.hasNext(); )
 640  
         {
 641  10
             Artifact artifact = (Artifact) i.next();
 642  
 
 643  10
             Element containerElement = createElement( component, "containerElement" );
 644  
 
 645  10
             if ( linkModules && isReactorProject( artifact.getGroupId(), artifact.getArtifactId() ) )
 646  
             {
 647  2
                 containerElement.addAttribute( "type", "module" );
 648  2
                 containerElement.addAttribute( "name", artifact.getArtifactId() );
 649  2
                 Element methodAttribute = createElement( containerElement, "attribute" );
 650  2
                 methodAttribute.addAttribute( "name", "method" );
 651  2
                 methodAttribute.addAttribute( "value", "6" );
 652  2
                 Element uriAttribute = createElement( containerElement, "attribute" );
 653  2
                 uriAttribute.addAttribute( "name", "URI" );
 654  2
                 uriAttribute.addAttribute( "value", "/lib/" + artifact.getArtifactId() + ".jar" );
 655  
             }
 656  8
             else if ( artifact.getFile() != null )
 657  
             {
 658  8
                 containerElement.addAttribute( "type", "library" );
 659  8
                 containerElement.addAttribute( "level", "module" );
 660  
 
 661  
                 //no longer needed in IntelliJ 6
 662  8
                 if ( StringUtils.isEmpty( ideaVersion ) || !ideaVersion.startsWith( "6" ) )
 663  
                 {
 664  8
                     containerElement.addAttribute( "name", artifact.getArtifactId() );
 665  
                 }
 666  
 
 667  8
                 Element methodAttribute = createElement( containerElement, "attribute" );
 668  8
                 methodAttribute.addAttribute( "name", "method" );
 669  8
                 methodAttribute.addAttribute( "value", "2" );
 670  8
                 Element uriAttribute = createElement( containerElement, "attribute" );
 671  8
                 uriAttribute.addAttribute( "name", "URI" );
 672  8
                 uriAttribute.addAttribute( "value", "/lib/" + artifact.getFile().getName() );
 673  8
                 Element urlElement = createElement( containerElement, "url" );
 674  8
                 urlElement.setText( getLibraryUrl( artifact ) );
 675  
             }
 676  
         }
 677  4
     }
 678  
 
 679  
     private void extractMacro( String path )
 680  
     {
 681  8
         if ( macros != null )
 682  
         {
 683  4
             Pattern p = Pattern.compile( ".*\\$([^\\$]+)\\$.*" );
 684  4
             Matcher matcher = p.matcher( path );
 685  8
             while ( matcher.find() )
 686  
             {
 687  4
                 String macro = matcher.group( 1 );
 688  4
                 macros.add( macro );
 689  
             }
 690  
         }
 691  8
     }
 692  
 
 693  
     private Library findLibrary( Artifact a )
 694  
     {
 695  80
         if ( libraries != null )
 696  
         {
 697  26
             for ( int j = 0; j < libraries.length; j++ )
 698  
             {
 699  16
                 Library library = libraries[j];
 700  16
                 if ( a.getArtifactId().equals( library.getName() ) )
 701  
                 {
 702  6
                     return library;
 703  
                 }
 704  
             }
 705  
         }
 706  
 
 707  74
         return null;
 708  
     }
 709  
 
 710  
     private List getExcludedDirectories( File target, List excludeList, List sourceFolders )
 711  
     {
 712  110
         List foundFolders = new ArrayList();
 713  
 
 714  110
         int totalDirs = 0, excludedDirs = 0;
 715  
 
 716  110
         if ( target.exists() && !excludeList.contains( target.getAbsolutePath() ) )
 717  
         {
 718  2
             File[] files = target.listFiles();
 719  
 
 720  6
             for ( int i = 0; i < files.length; i++ )
 721  
             {
 722  4
                 File file = files[i];
 723  4
                 if ( file.isDirectory() && !excludeList.contains( file.getAbsolutePath() ) )
 724  
                 {
 725  4
                     totalDirs++;
 726  
 
 727  4
                     String absolutePath = file.getAbsolutePath();
 728  4
                     String url = getModuleFileUrl( absolutePath );
 729  
 
 730  4
                     boolean addToExclude = true;
 731  4
                     for ( Iterator sources = sourceFolders.iterator(); sources.hasNext(); )
 732  
                     {
 733  8
                         String source = ( (Element) sources.next() ).attributeValue( "url" );
 734  8
                         if ( source.equals( url ) )
 735  
                         {
 736  0
                             addToExclude = false;
 737  0
                             break;
 738  
                         }
 739  8
                         else if ( source.indexOf( url ) == 0 )
 740  
                         {
 741  0
                             foundFolders.addAll(
 742  
                                 getExcludedDirectories( new File( absolutePath ), excludeList, sourceFolders ) );
 743  0
                             addToExclude = false;
 744  0
                             break;
 745  
                         }
 746  
                     }
 747  4
                     if ( addToExclude )
 748  
                     {
 749  4
                         excludedDirs++;
 750  4
                         foundFolders.add( absolutePath );
 751  
                     }
 752  
                 }
 753  
             }
 754  
 
 755  
             //if all directories are excluded, then just exclude the parent directory
 756  2
             if ( totalDirs > 0 && totalDirs == excludedDirs )
 757  
             {
 758  2
                 foundFolders.clear();
 759  
 
 760  2
                 foundFolders.add( target.getAbsolutePath() );
 761  
             }
 762  
         }
 763  108
         else if ( !target.exists() )
 764  
         {
 765  
             //might as well exclude a non-existent dir so that it won't show when it suddenly appears
 766  108
             foundFolders.add( target.getAbsolutePath() );
 767  
         }
 768  
 
 769  110
         return foundFolders;
 770  
     }
 771  
 
 772  
     /**
 773  
      * Adds the Web module to the (.iml) project file.
 774  
      *
 775  
      * @param module Xpp3Dom element
 776  
      */
 777  
     private void addWebModule( Element module )
 778  
     {
 779  
         // TODO: this is bad - reproducing war plugin defaults, etc!
 780  
         //   --> this is where the OGNL out of a plugin would be helpful as we could run package first and
 781  
         //       grab stuff from the mojo
 782  
 
 783  10
         String warWebapp = executedProject.getBuild().getDirectory() + "/" + executedProject.getArtifactId();
 784  10
         String warSrc = getPluginSetting( "maven-war-plugin", "warSourceDirectory", "src/main/webapp" );
 785  10
         String webXml = warSrc + "/WEB-INF/web.xml";
 786  
 
 787  10
         module.addAttribute( "type", "J2EE_WEB_MODULE" );
 788  
 
 789  10
         Element component = findComponent( module, "WebModuleBuildComponent" );
 790  10
         Element setting = findSetting( component, "EXPLODED_URL" );
 791  10
         setting.addAttribute( "value", getModuleFileUrl( warWebapp ) );
 792  
 
 793  10
         component = findComponent( module, "WebModuleProperties" );
 794  
 
 795  10
         removeOldElements( component, "containerElement" );
 796  10
         List artifacts = executedProject.getTestArtifacts();
 797  10
         for ( Iterator i = artifacts.iterator(); i.hasNext(); )
 798  
         {
 799  26
             Artifact artifact = (Artifact) i.next();
 800  
 
 801  26
             Element containerElement = createElement( component, "containerElement" );
 802  
 
 803  26
             if ( linkModules && isReactorProject( artifact.getGroupId(), artifact.getArtifactId() ) )
 804  
             {
 805  2
                 containerElement.addAttribute( "type", "module" );
 806  2
                 containerElement.addAttribute( "name", artifact.getArtifactId() );
 807  2
                 Element methodAttribute = createElement( containerElement, "attribute" );
 808  2
                 methodAttribute.addAttribute( "name", "method" );
 809  2
                 methodAttribute.addAttribute( "value", "5" );
 810  2
                 Element uriAttribute = createElement( containerElement, "attribute" );
 811  2
                 uriAttribute.addAttribute( "name", "URI" );
 812  2
                 uriAttribute.addAttribute( "value", "/WEB-INF/lib/" + artifact.getArtifactId() + "-"
 813  
                     + artifact.getVersion() + ".jar" );
 814  
             }
 815  24
             else if ( artifact.getFile() != null )
 816  
             {
 817  24
                 containerElement.addAttribute( "type", "library" );
 818  24
                 containerElement.addAttribute( "level", "module" );
 819  24
                 Element methodAttribute = createElement( containerElement, "attribute" );
 820  24
                 methodAttribute.addAttribute( "name", "method" );
 821  24
                 if ( Artifact.SCOPE_PROVIDED.equalsIgnoreCase( artifact.getScope() )
 822  
                     || Artifact.SCOPE_SYSTEM.equalsIgnoreCase( artifact.getScope() )
 823  
                     || Artifact.SCOPE_TEST.equalsIgnoreCase( artifact.getScope() ) )
 824  
                 {
 825  
                     // If scope is provided, system or test - do not package.
 826  12
                     methodAttribute.addAttribute( "value", "0" );
 827  
                 }
 828  
                 else
 829  
                 {
 830  12
                     methodAttribute.addAttribute( "value", "1" ); // IntelliJ 5.0.2 is bugged and doesn't read it
 831  
                 }
 832  24
                 Element uriAttribute = createElement( containerElement, "attribute" );
 833  24
                 uriAttribute.addAttribute( "name", "URI" );
 834  24
                 uriAttribute.addAttribute( "value", "/WEB-INF/lib/" + artifact.getFile().getName() );
 835  24
                 Element url = createElement( containerElement, "url" );
 836  24
                 url.setText( getLibraryUrl( artifact ) );
 837  
             }
 838  
         }
 839  
 
 840  10
         addDeploymentDescriptor( component, "web.xml", "2.3", webXml );
 841  
 
 842  10
         Element element = findElement( component, "webroots" );
 843  10
         removeOldElements( element, "root" );
 844  
 
 845  10
         element = createElement( element, "root" );
 846  10
         element.addAttribute( "relative", "/" );
 847  10
         element.addAttribute( "url", getModuleFileUrl( warSrc ) );
 848  10
     }
 849  
 
 850  
     private void addPluginModule( Element module )
 851  
     {
 852  0
         module.addAttribute( "type", "PLUGIN_MODULE" );
 853  
 
 854  
         // this is where the META-INF/plugin.xml file is located
 855  0
         Element pluginDevElement = createElement( module, "component" );
 856  0
         pluginDevElement.addAttribute( "name", "DevKit.ModuleBuildProperties" );
 857  0
         pluginDevElement.addAttribute( "url", getModuleFileUrl( "src/main/resources/META-INF/plugin.xml" ) );
 858  0
     }
 859  
 
 860  
     /**
 861  
      * Translate the relative path of the file into module path
 862  
      *
 863  
      * @param basedir File to use as basedir
 864  
      * @param path    Absolute path string to translate to ModuleFileUrl
 865  
      * @return moduleFileUrl Translated Module File URL
 866  
      */
 867  
     private String getModuleFileUrl( File basedir, String path )
 868  
     {
 869  288
         return "file://$MODULE_DIR$/" + toRelative( basedir.getAbsolutePath(), path );
 870  
     }
 871  
 
 872  
     private String getModuleFileUrl( String file )
 873  
     {
 874  288
         return getModuleFileUrl( executedProject.getBasedir(), file );
 875  
     }
 876  
 
 877  
     /**
 878  
      * Adds a sourceFolder element to IDEA (.iml) project file
 879  
      *
 880  
      * @param content   Xpp3Dom element
 881  
      * @param directory Directory to set as url.
 882  
      * @param isTest    True if directory isTestSource.
 883  
      */
 884  
     private void addSourceFolder( Element content, String directory, boolean isTest )
 885  
     {
 886  136
         if ( !StringUtils.isEmpty( directory ) && new File( directory ).isDirectory() )
 887  
         {
 888  68
             Element sourceFolder = createElement( content, "sourceFolder" );
 889  68
             sourceFolder.addAttribute( "url", getModuleFileUrl( directory ) );
 890  68
             sourceFolder.addAttribute( "isTestSource", Boolean.toString( isTest ) );
 891  
         }
 892  136
     }
 893  
 
 894  
     private void addExcludeFolder( Element content, String directory )
 895  
     {
 896  40
         Element excludeFolder = createElement( content, "excludeFolder" );
 897  40
         excludeFolder.addAttribute( "url", getModuleFileUrl( directory ) );
 898  40
     }
 899  
 
 900  
     private boolean isReactorProject( String groupId, String artifactId )
 901  
     {
 902  114
         if ( reactorProjects != null )
 903  
         {
 904  112
             for ( Iterator j = reactorProjects.iterator(); j.hasNext(); )
 905  
             {
 906  336
                 MavenProject p = (MavenProject) j.next();
 907  336
                 if ( p.getGroupId().equals( groupId ) && p.getArtifactId().equals( artifactId ) )
 908  
                 {
 909  10
                     return true;
 910  
                 }
 911  
             }
 912  
         }
 913  104
         return false;
 914  
     }
 915  
 
 916  
     private void resolveClassifier( Element element, Artifact a, String classifier )
 917  
     {
 918  8
         String id = a.getId() + '-' + classifier;
 919  
 
 920  
         String path;
 921  8
         if ( attemptedDownloads.containsKey( id ) )
 922  
         {
 923  0
             getLog().debug( id + " was already downloaded." );
 924  0
             path = (String) attemptedDownloads.get( id );
 925  
         }
 926  
         else
 927  
         {
 928  8
             getLog().debug( id + " was not attempted to be downloaded yet: trying..." );
 929  8
             path = resolveClassifiedArtifact( a, classifier );
 930  8
             attemptedDownloads.put( id, path );
 931  
         }
 932  
 
 933  8
         if ( path != null )
 934  
         {
 935  6
             String jarPath = "jar://" + path + "!/";
 936  6
             getLog().debug( "Setting " + classifier + " for " + id + " to " + jarPath );
 937  6
             removeOldElements( element, "root" );
 938  6
             createElement( element, "root" ).addAttribute( "url", jarPath );
 939  
         }
 940  8
     }
 941  
 
 942  
     private String resolveClassifiedArtifact( Artifact artifact, String classifier )
 943  
     {
 944  8
         String basePath = artifact.getFile().getAbsolutePath().replace( '\\', '/' );
 945  8
         int delIndex = basePath.indexOf( ".jar" );
 946  8
         if ( delIndex < 0 )
 947  
         {
 948  0
             return null;
 949  
         }
 950  
 
 951  8
         List remoteRepos = executedProject.getRemoteArtifactRepositories();
 952  
         try
 953  
         {
 954  8
             Artifact classifiedArtifact = artifactFactory.createArtifactWithClassifier( artifact.getGroupId(),
 955  
                                                                                         artifact.getArtifactId(),
 956  
                                                                                         artifact.getVersion(),
 957  
                                                                                         artifact.getType(),
 958  
                                                                                         classifier );
 959  8
             String dstFilename = basePath.substring( 0, delIndex ) + '-' + classifier + ".jar";
 960  8
             File dstFile = new File( dstFilename );
 961  8
             classifiedArtifact.setFile( dstFile );
 962  
             //this check is here because wagonManager does not seem to check if the remote file is newer
 963  
             //    or such feature is not working
 964  8
             if ( !dstFile.exists() )
 965  
             {
 966  2
                 wagonManager.getArtifact( classifiedArtifact, remoteRepos );
 967  
             }
 968  6
             return dstFile.getAbsolutePath().replace( '\\', '/' );
 969  
         }
 970  0
         catch ( TransferFailedException e )
 971  
         {
 972  0
             getLog().debug( e );
 973  0
             return null;
 974  
         }
 975  2
         catch ( ResourceDoesNotExistException e )
 976  
         {
 977  2
             getLog().debug( e );
 978  2
             return null;
 979  
         }
 980  
     }
 981  
 
 982  
     /**
 983  
      * Returns an Xpp3Dom element (setting).
 984  
      *
 985  
      * @param component Xpp3Dom element
 986  
      * @param name      Setting attribute to find
 987  
      * @return setting Xpp3Dom element
 988  
      */
 989  
     private Element findSetting( Element component, String name )
 990  
     {
 991  14
         return findElement( component, "setting", name );
 992  
     }
 993  
 
 994  
     private String getLibraryUrl( Artifact artifact )
 995  
     {
 996  164
         return "jar://" + convertDriveLetter( artifact.getFile().getAbsolutePath() ).replace( '\\', '/' ) + "!/";
 997  
     }
 998  
 
 999  
     private Element addDeploymentDescriptor( Element component, String name, String version, String file )
 1000  
     {
 1001  16
         Element deploymentDescriptor = findElement( component, "deploymentDescriptor" );
 1002  
 
 1003  16
         if ( deploymentDescriptor.attributeValue( "version" ) == null )
 1004  
         {
 1005  0
             deploymentDescriptor.addAttribute( "version", version );
 1006  
         }
 1007  
 
 1008  16
         if ( deploymentDescriptor.attributeValue( "name" ) == null )
 1009  
         {
 1010  0
             deploymentDescriptor.addAttribute( "name", name );
 1011  
         }
 1012  
 
 1013  16
         deploymentDescriptor.addAttribute( "optional", "false" );
 1014  
 
 1015  16
         if ( deploymentDescriptorFile == null )
 1016  
         {
 1017  14
             deploymentDescriptorFile = file;
 1018  
         }
 1019  
 
 1020  16
         deploymentDescriptor.addAttribute( "url", getModuleFileUrl( deploymentDescriptorFile ) );
 1021  
 
 1022  16
         return deploymentDescriptor;
 1023  
     }
 1024  
 }