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  51
 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  3
     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  6
         super.initParam( project, artifactFactory, localRepo, artifactResolver, artifactMetadataSource, log,
 200  
                          overwrite );
 201  
 
 202  6
         this.reactorProjects = reactorProjects;
 203  
 
 204  6
         this.wagonManager = wagonManager;
 205  
 
 206  6
         this.linkModules = linkModules;
 207  
 
 208  6
         this.useFullNames = useFullNames;
 209  
 
 210  6
         this.downloadSources = downloadSources;
 211  
 
 212  6
         this.sourceClassifier = sourceClassifier;
 213  
 
 214  6
         this.downloadJavadocs = downloadJavadocs;
 215  
 
 216  6
         this.javadocClassifier = javadocClassifier;
 217  
 
 218  6
         this.libraries = libraries;
 219  
 
 220  6
         this.macros = macros;
 221  
 
 222  6
         this.exclude = exclude;
 223  
 
 224  6
         this.dependenciesAsLibraries = useShortDependencyNames;
 225  
 
 226  6
         this.deploymentDescriptorFile = deploymentDescriptorFile;
 227  
 
 228  6
         this.ideaPlugin = ideaPlugin;
 229  
 
 230  6
         this.ideaVersion = ideaVersion;
 231  6
     }
 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  45
             doDependencyResolution( executedProject, localRepo );
 245  
         }
 246  0
         catch ( Exception e )
 247  
         {
 248  0
             throw new MojoExecutionException( "Unable to build project dependencies.", e );
 249  45
         }
 250  
 
 251  45
         rewriteModule();
 252  45
     }
 253  
 
 254  
     public void rewriteModule()
 255  
         throws MojoExecutionException
 256  
     {
 257  51
         File moduleFile = new File( executedProject.getBasedir(), executedProject.getArtifactId() + ".iml" );
 258  
         try
 259  
         {
 260  51
             Document document = readXmlDocument( moduleFile, "module.xml" );
 261  
 
 262  51
             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  51
             if ( "war".equals( executedProject.getPackaging() ) )
 267  
             {
 268  15
                 addWebModule( module );
 269  
             }
 270  36
             else if ( "ejb".equals( executedProject.getPackaging() ) )
 271  
             {
 272  6
                 addEjbModule( module );
 273  
             }
 274  30
             else if ( "ear".equals( executedProject.getPackaging() ) )
 275  
             {
 276  3
                 addEarModule( module );
 277  
             }
 278  27
             else if ( ideaPlugin )
 279  
             {
 280  0
                 addPluginModule( module );
 281  
             }
 282  
 
 283  51
             Element component = findComponent( module, "NewModuleRootManager" );
 284  51
             Element output = findElement( component, "output" );
 285  51
             output.addAttribute( "url", getModuleFileUrl( executedProject.getBuild().getOutputDirectory() ) );
 286  
 
 287  51
             Element outputTest = findElement( component, "output-test" );
 288  51
             outputTest.addAttribute( "url", getModuleFileUrl( executedProject.getBuild().getTestOutputDirectory() ) );
 289  
 
 290  51
             Element content = findElement( component, "content" );
 291  
 
 292  51
             removeOldElements( content, "sourceFolder" );
 293  
 
 294  51
             for ( Iterator i = executedProject.getCompileSourceRoots().iterator(); i.hasNext(); )
 295  
             {
 296  51
                 String directory = (String) i.next();
 297  51
                 addSourceFolder( content, directory, false );
 298  
             }
 299  51
             for ( Iterator i = executedProject.getTestCompileSourceRoots().iterator(); i.hasNext(); )
 300  
             {
 301  51
                 String directory = (String) i.next();
 302  51
                 addSourceFolder( content, directory, true );
 303  
             }
 304  
 
 305  51
             for ( Iterator i = executedProject.getBuild().getResources().iterator(); i.hasNext(); )
 306  
             {
 307  51
                 Resource resource = (Resource) i.next();
 308  51
                 String directory = resource.getDirectory();
 309  51
                 if ( resource.getTargetPath() == null && !resource.isFiltering() )
 310  
                 {
 311  51
                     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  51
             for ( Iterator i = executedProject.getBuild().getTestResources().iterator(); i.hasNext(); )
 322  
             {
 323  51
                 Resource resource = (Resource) i.next();
 324  51
                 String directory = resource.getDirectory();
 325  51
                 if ( resource.getTargetPath() == null && !resource.isFiltering() )
 326  
                 {
 327  51
                     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  51
             removeOldElements( content, "excludeFolder" );
 338  
 
 339  
             //For excludeFolder
 340  51
             File target = new File( executedProject.getBuild().getDirectory() );
 341  51
             File classes = new File( executedProject.getBuild().getOutputDirectory() );
 342  51
             File testClasses = new File( executedProject.getBuild().getTestOutputDirectory() );
 343  
 
 344  51
             List sourceFolders = content.elements( "sourceFolder" );
 345  
 
 346  51
             List filteredExcludes = new ArrayList();
 347  51
             filteredExcludes.addAll( getExcludedDirectories( target, filteredExcludes, sourceFolders ) );
 348  51
             filteredExcludes.addAll( getExcludedDirectories( classes, filteredExcludes, sourceFolders ) );
 349  51
             filteredExcludes.addAll( getExcludedDirectories( testClasses, filteredExcludes, sourceFolders ) );
 350  
 
 351  51
             if ( exclude != null )
 352  
             {
 353  6
                 String[] dirs = exclude.split( "[,\\s]+" );
 354  18
                 for ( int i = 0; i < dirs.length; i++ )
 355  
                 {
 356  12
                     File excludedDir = new File( executedProject.getBasedir(), dirs[i] );
 357  12
                     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  51
             ArrayList actuallyExcluded = new ArrayList();
 367  51
             Collections.sort( filteredExcludes );
 368  51
             for ( Iterator i = filteredExcludes.iterator(); i.hasNext(); )
 369  
             {
 370  165
                 String dirToExclude = i.next().toString();
 371  165
                 String dirToExcludeTemp = dirToExclude.replace( '\\', '/' );
 372  165
                 boolean addExclude = true;
 373  165
                 for ( Iterator iterator = actuallyExcluded.iterator(); iterator.hasNext(); )
 374  
                 {
 375  135
                     String dir = iterator.next().toString();
 376  135
                     String dirTemp = dir.replace( '\\', '/' );
 377  135
                     if ( dirToExcludeTemp.startsWith( dirTemp + "/" ) )
 378  
                     {
 379  105
                         addExclude = false;
 380  105
                         break;
 381  
                     }
 382  30
                     else if ( dir.startsWith( dirToExcludeTemp + "/" ) )
 383  
                     {
 384  0
                         actuallyExcluded.remove( dir );
 385  
                     }
 386  
                 }
 387  
 
 388  165
                 if ( addExclude )
 389  
                 {
 390  60
                     actuallyExcluded.add( dirToExclude );
 391  60
                     addExcludeFolder( content, dirToExclude );
 392  
                 }
 393  
             }
 394  
 
 395  
             //Remove default exclusion for output dirs if there are sources in it
 396  51
             String outputModuleUrl = getModuleFileUrl( executedProject.getBuild().getOutputDirectory() );
 397  51
             String testOutputModuleUrl = getModuleFileUrl( executedProject.getBuild().getTestOutputDirectory() );
 398  51
             for ( Iterator i = content.elements( "sourceFolder" ).iterator(); i.hasNext(); )
 399  
             {
 400  102
                 Element sourceFolder = (Element) i.next();
 401  102
                 String sourceUrl = sourceFolder.attributeValue( "url" ).replace( '\\', '/' );
 402  102
                 if ( sourceUrl.startsWith( outputModuleUrl + "/" ) || sourceUrl.startsWith( testOutputModuleUrl ) )
 403  
                 {
 404  0
                     component.remove( component.element( "exclude-output" ) );
 405  0
                     break;
 406  
                 }
 407  
             }
 408  
 
 409  51
             rewriteDependencies( component );
 410  
 
 411  51
             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  51
         }
 421  51
     }
 422  
 
 423  
     private void rewriteDependencies( Element component )
 424  
     {
 425  51
         Map modulesByName = new HashMap();
 426  51
         Map modulesByUrl = new HashMap();
 427  51
         Set unusedModules = new HashSet();
 428  51
         for ( Iterator children = component.elementIterator( "orderEntry" ); children.hasNext(); )
 429  
         {
 430  219
             Element orderEntry = (Element) children.next();
 431  
 
 432  219
             String type = orderEntry.attributeValue( "type" );
 433  219
             if ( "module".equals( type ) )
 434  
             {
 435  9
                 modulesByName.put( orderEntry.attributeValue( "module-name" ), orderEntry );
 436  
             }
 437  210
             else if ( "module-library".equals( type ) )
 438  
             {
 439  
                 // keep track for later so we know what is left
 440  108
                 unusedModules.add( orderEntry );
 441  
 
 442  108
                 Element lib = orderEntry.element( "library" );
 443  108
                 String name = lib.attributeValue( "name" );
 444  108
                 if ( name != null )
 445  
                 {
 446  12
                     modulesByName.put( name, orderEntry );
 447  
                 }
 448  
                 else
 449  
                 {
 450  96
                     Element classesChild = lib.element( "CLASSES" );
 451  96
                     if ( classesChild != null )
 452  
                     {
 453  96
                         Element rootChild = classesChild.element( "root" );
 454  96
                         if ( rootChild != null )
 455  
                         {
 456  96
                             String url = rootChild.attributeValue( "url" );
 457  96
                             if ( url != null )
 458  
                             {
 459  
                                 // Need to ignore case because of Windows drive letters
 460  96
                                 modulesByUrl.put( url.toLowerCase(), orderEntry );
 461  
                             }
 462  
                         }
 463  
                     }
 464  
                 }
 465  
             }
 466  
         }
 467  
 
 468  51
         List testClasspathElements = executedProject.getTestArtifacts();
 469  51
         for ( Iterator i = testClasspathElements.iterator(); i.hasNext(); )
 470  
         {
 471  120
             Artifact a = (Artifact) i.next();
 472  
 
 473  120
             Library library = findLibrary( a );
 474  120
             if ( library != null && library.isExclude() )
 475  
             {
 476  3
                 continue;
 477  
             }
 478  
 
 479  
             String moduleName;
 480  117
             if ( useFullNames )
 481  
             {
 482  6
                 moduleName = a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getType() + ':' + a.getVersion();
 483  
             }
 484  
             else
 485  
             {
 486  111
                 moduleName = a.getArtifactId();
 487  
             }
 488  
 
 489  117
             Element dep = (Element) modulesByName.get( moduleName );
 490  
 
 491  117
             if ( dep == null )
 492  
             {
 493  
                 // Need to ignore case because of Windows drive letters
 494  96
                 dep = (Element) modulesByUrl.get( getLibraryUrl( a ).toLowerCase() );
 495  
             }
 496  
 
 497  117
             if ( dep != null )
 498  
             {
 499  117
                 unusedModules.remove( dep );
 500  
             }
 501  
             else
 502  
             {
 503  0
                 dep = createElement( component, "orderEntry" );
 504  
             }
 505  
 
 506  117
             boolean isIdeaModule = false;
 507  117
             if ( linkModules )
 508  
             {
 509  117
                 isIdeaModule = isReactorProject( a.getGroupId(), a.getArtifactId() );
 510  
 
 511  117
                 if ( isIdeaModule )
 512  
                 {
 513  9
                     dep.addAttribute( "type", "module" );
 514  9
                     dep.addAttribute( "module-name", moduleName );
 515  
                 }
 516  
             }
 517  
 
 518  117
             if ( a.getFile() != null && !isIdeaModule )
 519  
             {
 520  108
                 dep.addAttribute( "type", "module-library" );
 521  
 
 522  108
                 Element lib = dep.element( "library" );
 523  
 
 524  108
                 if ( lib == null )
 525  
                 {
 526  0
                     lib = createElement( dep, "library" );
 527  
                 }
 528  
 
 529  108
                 if ( dependenciesAsLibraries )
 530  
                 {
 531  6
                     lib.addAttribute( "name", moduleName );
 532  
                 }
 533  
 
 534  
                 // replace classes
 535  108
                 removeOldElements( lib, "CLASSES" );
 536  108
                 Element classes = createElement( lib, "CLASSES" );
 537  108
                 if ( library != null && library.getSplitClasses().length > 0 )
 538  
                 {
 539  6
                     lib.addAttribute( "name", moduleName );
 540  6
                     String[] libraryClasses = library.getSplitClasses();
 541  12
                     for ( int k = 0; k < libraryClasses.length; k++ )
 542  
                     {
 543  6
                         String classpath = libraryClasses[k];
 544  6
                         extractMacro( classpath );
 545  6
                         Element classEl = createElement( classes, "root" );
 546  6
                         classEl.addAttribute( "url", classpath );
 547  
                     }
 548  
                 }
 549  
                 else
 550  
                 {
 551  102
                     createElement( classes, "root" ).addAttribute( "url", getLibraryUrl( a ) );
 552  
                 }
 553  
 
 554  108
                 if ( library != null && library.getSplitSources().length > 0 )
 555  
                 {
 556  6
                     removeOldElements( lib, "SOURCES" );
 557  6
                     Element sourcesElement = createElement( lib, "SOURCES" );
 558  6
                     String[] sources = library.getSplitSources();
 559  12
                     for ( int k = 0; k < sources.length; k++ )
 560  
                     {
 561  6
                         String source = sources[k];
 562  6
                         extractMacro( source );
 563  6
                         Element sourceEl = createElement( sourcesElement, "root" );
 564  6
                         sourceEl.addAttribute( "url", source );
 565  
                     }
 566  
                 }
 567  102
                 else if ( downloadSources )
 568  
                 {
 569  6
                     resolveClassifier( createOrGetElement( lib, "SOURCES" ), a, sourceClassifier );
 570  
                 }
 571  
 
 572  108
                 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  108
                 else if ( downloadJavadocs )
 586  
                 {
 587  6
                     resolveClassifier( createOrGetElement( lib, "JAVADOC" ), a, javadocClassifier );
 588  
                 }
 589  
             }
 590  
         }
 591  
 
 592  51
         for ( Iterator i = unusedModules.iterator(); i.hasNext(); )
 593  
         {
 594  0
             Element orderEntry = (Element) i.next();
 595  
 
 596  0
             component.remove( orderEntry );
 597  
         }
 598  51
     }
 599  
 
 600  
     private Element createOrGetElement( Element lib, String name )
 601  
     {
 602  12
         Element el = lib.element( name );
 603  
 
 604  12
         if ( el == null )
 605  
         {
 606  0
             el = createElement( lib, name );
 607  
         }
 608  12
         return el;
 609  
     }
 610  
 
 611  
     private void addEarModule( Element module )
 612  
     {
 613  3
         module.addAttribute( "type", "J2EE_APPLICATION_MODULE" );
 614  3
         Element component = findComponent( module, "ApplicationModuleProperties" );
 615  3
         addDeploymentDescriptor( component, "application.xml", "1.3",
 616  
                                  executedProject.getBuild().getDirectory() + "/application.xml" );
 617  3
     }
 618  
 
 619  
     private void addEjbModule( Element module )
 620  
     {
 621  6
         String ejbVersion = getPluginSetting( "maven-ejb-plugin", "ejbVersion", "2.x" );
 622  
 
 623  6
         module.addAttribute( "type", "J2EE_EJB_MODULE" );
 624  
 
 625  6
         String explodedDir = executedProject.getBuild().getDirectory() + "/" + executedProject.getArtifactId();
 626  
 
 627  6
         Element component = findComponent( module, "EjbModuleBuildComponent" );
 628  
 
 629  6
         Element setting = findSetting( component, "EXPLODED_URL" );
 630  6
         setting.addAttribute( "value", getModuleFileUrl( explodedDir ) );
 631  
 
 632  6
         component = findComponent( module, "EjbModuleProperties" );
 633  6
         Element deployDescElement =
 634  
             addDeploymentDescriptor( component, "ejb-jar.xml", ejbVersion, "src/main/resources/META-INF/ejb-jar.xml" );
 635  6
         deployDescElement.addAttribute( "optional", ejbVersion.startsWith( "3" ) + "" );
 636  
 
 637  6
         removeOldElements( component, "containerElement" );
 638  6
         List artifacts = executedProject.getTestArtifacts();
 639  6
         for ( Iterator i = artifacts.iterator(); i.hasNext(); )
 640  
         {
 641  15
             Artifact artifact = (Artifact) i.next();
 642  
 
 643  15
             Element containerElement = createElement( component, "containerElement" );
 644  
 
 645  15
             if ( linkModules && isReactorProject( artifact.getGroupId(), artifact.getArtifactId() ) )
 646  
             {
 647  3
                 containerElement.addAttribute( "type", "module" );
 648  3
                 containerElement.addAttribute( "name", artifact.getArtifactId() );
 649  3
                 Element methodAttribute = createElement( containerElement, "attribute" );
 650  3
                 methodAttribute.addAttribute( "name", "method" );
 651  3
                 methodAttribute.addAttribute( "value", "6" );
 652  3
                 Element uriAttribute = createElement( containerElement, "attribute" );
 653  3
                 uriAttribute.addAttribute( "name", "URI" );
 654  3
                 uriAttribute.addAttribute( "value", "/lib/" + artifact.getArtifactId() + ".jar" );
 655  
             }
 656  12
             else if ( artifact.getFile() != null )
 657  
             {
 658  12
                 containerElement.addAttribute( "type", "library" );
 659  12
                 containerElement.addAttribute( "level", "module" );
 660  
 
 661  
                 //no longer needed in IntelliJ 6
 662  12
                 if ( StringUtils.isEmpty( ideaVersion ) || !ideaVersion.startsWith( "6" ) )
 663  
                 {
 664  12
                     containerElement.addAttribute( "name", artifact.getArtifactId() );
 665  
                 }
 666  
 
 667  12
                 Element methodAttribute = createElement( containerElement, "attribute" );
 668  12
                 methodAttribute.addAttribute( "name", "method" );
 669  12
                 methodAttribute.addAttribute( "value", "2" );
 670  12
                 Element uriAttribute = createElement( containerElement, "attribute" );
 671  12
                 uriAttribute.addAttribute( "name", "URI" );
 672  12
                 uriAttribute.addAttribute( "value", "/lib/" + artifact.getFile().getName() );
 673  12
                 Element urlElement = createElement( containerElement, "url" );
 674  12
                 urlElement.setText( getLibraryUrl( artifact ) );
 675  
             }
 676  
         }
 677  6
     }
 678  
 
 679  
     private void extractMacro( String path )
 680  
     {
 681  12
         if ( macros != null )
 682  
         {
 683  6
             Pattern p = Pattern.compile( ".*\\$([^\\$]+)\\$.*" );
 684  6
             Matcher matcher = p.matcher( path );
 685  12
             while ( matcher.find() )
 686  
             {
 687  6
                 String macro = matcher.group( 1 );
 688  6
                 macros.add( macro );
 689  
             }
 690  
         }
 691  12
     }
 692  
 
 693  
     private Library findLibrary( Artifact a )
 694  
     {
 695  120
         if ( libraries != null )
 696  
         {
 697  39
             for ( int j = 0; j < libraries.length; j++ )
 698  
             {
 699  24
                 Library library = libraries[j];
 700  24
                 if ( a.getArtifactId().equals( library.getName() ) )
 701  
                 {
 702  9
                     return library;
 703  
                 }
 704  
             }
 705  
         }
 706  
 
 707  111
         return null;
 708  
     }
 709  
 
 710  
     private List getExcludedDirectories( File target, List excludeList, List sourceFolders )
 711  
     {
 712  165
         List foundFolders = new ArrayList();
 713  
 
 714  165
         int totalDirs = 0, excludedDirs = 0;
 715  
 
 716  165
         if ( target.exists() && !excludeList.contains( target.getAbsolutePath() ) )
 717  
         {
 718  3
             File[] files = target.listFiles();
 719  
 
 720  9
             for ( int i = 0; i < files.length; i++ )
 721  
             {
 722  6
                 File file = files[i];
 723  6
                 if ( file.isDirectory() && !excludeList.contains( file.getAbsolutePath() ) )
 724  
                 {
 725  6
                     totalDirs++;
 726  
 
 727  6
                     String absolutePath = file.getAbsolutePath();
 728  6
                     String url = getModuleFileUrl( absolutePath );
 729  
 
 730  6
                     boolean addToExclude = true;
 731  6
                     for ( Iterator sources = sourceFolders.iterator(); sources.hasNext(); )
 732  
                     {
 733  12
                         String source = ( (Element) sources.next() ).attributeValue( "url" );
 734  12
                         if ( source.equals( url ) )
 735  
                         {
 736  0
                             addToExclude = false;
 737  0
                             break;
 738  
                         }
 739  12
                         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  6
                     if ( addToExclude )
 748  
                     {
 749  6
                         excludedDirs++;
 750  6
                         foundFolders.add( absolutePath );
 751  
                     }
 752  
                 }
 753  
             }
 754  
 
 755  
             //if all directories are excluded, then just exclude the parent directory
 756  3
             if ( totalDirs > 0 && totalDirs == excludedDirs )
 757  
             {
 758  3
                 foundFolders.clear();
 759  
 
 760  3
                 foundFolders.add( target.getAbsolutePath() );
 761  
             }
 762  
         }
 763  162
         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  162
             foundFolders.add( target.getAbsolutePath() );
 767  
         }
 768  
 
 769  165
         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  15
         String warWebapp = executedProject.getBuild().getDirectory() + "/" + executedProject.getArtifactId();
 784  15
         String warSrc = getPluginSetting( "maven-war-plugin", "warSourceDirectory", "src/main/webapp" );
 785  15
         String webXml = warSrc + "/WEB-INF/web.xml";
 786  
 
 787  15
         module.addAttribute( "type", "J2EE_WEB_MODULE" );
 788  
 
 789  15
         Element component = findComponent( module, "WebModuleBuildComponent" );
 790  15
         Element setting = findSetting( component, "EXPLODED_URL" );
 791  15
         setting.addAttribute( "value", getModuleFileUrl( warWebapp ) );
 792  
 
 793  15
         component = findComponent( module, "WebModuleProperties" );
 794  
 
 795  15
         removeOldElements( component, "containerElement" );
 796  15
         List artifacts = executedProject.getTestArtifacts();
 797  15
         for ( Iterator i = artifacts.iterator(); i.hasNext(); )
 798  
         {
 799  39
             Artifact artifact = (Artifact) i.next();
 800  
 
 801  39
             Element containerElement = createElement( component, "containerElement" );
 802  
 
 803  39
             if ( linkModules && isReactorProject( artifact.getGroupId(), artifact.getArtifactId() ) )
 804  
             {
 805  3
                 containerElement.addAttribute( "type", "module" );
 806  3
                 containerElement.addAttribute( "name", artifact.getArtifactId() );
 807  3
                 Element methodAttribute = createElement( containerElement, "attribute" );
 808  3
                 methodAttribute.addAttribute( "name", "method" );
 809  3
                 methodAttribute.addAttribute( "value", "5" );
 810  3
                 Element uriAttribute = createElement( containerElement, "attribute" );
 811  3
                 uriAttribute.addAttribute( "name", "URI" );
 812  3
                 uriAttribute.addAttribute( "value", "/WEB-INF/lib/" + artifact.getArtifactId() + "-"
 813  
                     + artifact.getVersion() + ".jar" );
 814  
             }
 815  36
             else if ( artifact.getFile() != null )
 816  
             {
 817  36
                 containerElement.addAttribute( "type", "library" );
 818  36
                 containerElement.addAttribute( "level", "module" );
 819  36
                 Element methodAttribute = createElement( containerElement, "attribute" );
 820  36
                 methodAttribute.addAttribute( "name", "method" );
 821  36
                 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  18
                     methodAttribute.addAttribute( "value", "0" );
 827  
                 }
 828  
                 else
 829  
                 {
 830  18
                     methodAttribute.addAttribute( "value", "1" ); // IntelliJ 5.0.2 is bugged and doesn't read it
 831  
                 }
 832  36
                 Element uriAttribute = createElement( containerElement, "attribute" );
 833  36
                 uriAttribute.addAttribute( "name", "URI" );
 834  36
                 uriAttribute.addAttribute( "value", "/WEB-INF/lib/" + artifact.getFile().getName() );
 835  36
                 Element url = createElement( containerElement, "url" );
 836  36
                 url.setText( getLibraryUrl( artifact ) );
 837  
             }
 838  
         }
 839  
 
 840  15
         addDeploymentDescriptor( component, "web.xml", "2.3", webXml );
 841  
 
 842  15
         Element element = findElement( component, "webroots" );
 843  15
         removeOldElements( element, "root" );
 844  
 
 845  15
         element = createElement( element, "root" );
 846  15
         element.addAttribute( "relative", "/" );
 847  15
         element.addAttribute( "url", getModuleFileUrl( warSrc ) );
 848  15
     }
 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  432
         return "file://$MODULE_DIR$/" + toRelative( basedir.getAbsolutePath(), path );
 870  
     }
 871  
 
 872  
     private String getModuleFileUrl( String file )
 873  
     {
 874  432
         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  204
         if ( !StringUtils.isEmpty( directory ) && new File( directory ).isDirectory() )
 887  
         {
 888  102
             Element sourceFolder = createElement( content, "sourceFolder" );
 889  102
             sourceFolder.addAttribute( "url", getModuleFileUrl( directory ) );
 890  102
             sourceFolder.addAttribute( "isTestSource", Boolean.toString( isTest ) );
 891  
         }
 892  204
     }
 893  
 
 894  
     private void addExcludeFolder( Element content, String directory )
 895  
     {
 896  60
         Element excludeFolder = createElement( content, "excludeFolder" );
 897  60
         excludeFolder.addAttribute( "url", getModuleFileUrl( directory ) );
 898  60
     }
 899  
 
 900  
     private boolean isReactorProject( String groupId, String artifactId )
 901  
     {
 902  171
         if ( reactorProjects != null )
 903  
         {
 904  168
             for ( Iterator j = reactorProjects.iterator(); j.hasNext(); )
 905  
             {
 906  504
                 MavenProject p = (MavenProject) j.next();
 907  504
                 if ( p.getGroupId().equals( groupId ) && p.getArtifactId().equals( artifactId ) )
 908  
                 {
 909  15
                     return true;
 910  
                 }
 911  
             }
 912  
         }
 913  156
         return false;
 914  
     }
 915  
 
 916  
     private void resolveClassifier( Element element, Artifact a, String classifier )
 917  
     {
 918  12
         String id = a.getId() + '-' + classifier;
 919  
 
 920  
         String path;
 921  12
         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  12
             getLog().debug( id + " was not attempted to be downloaded yet: trying..." );
 929  12
             path = resolveClassifiedArtifact( a, classifier );
 930  12
             attemptedDownloads.put( id, path );
 931  
         }
 932  
 
 933  12
         if ( path != null )
 934  
         {
 935  9
             String jarPath = "jar://" + path + "!/";
 936  9
             getLog().debug( "Setting " + classifier + " for " + id + " to " + jarPath );
 937  9
             removeOldElements( element, "root" );
 938  9
             createElement( element, "root" ).addAttribute( "url", jarPath );
 939  
         }
 940  12
     }
 941  
 
 942  
     private String resolveClassifiedArtifact( Artifact artifact, String classifier )
 943  
     {
 944  12
         String basePath = artifact.getFile().getAbsolutePath().replace( '\\', '/' );
 945  12
         int delIndex = basePath.indexOf( ".jar" );
 946  12
         if ( delIndex < 0 )
 947  
         {
 948  0
             return null;
 949  
         }
 950  
 
 951  12
         List remoteRepos = executedProject.getRemoteArtifactRepositories();
 952  
         try
 953  
         {
 954  12
             Artifact classifiedArtifact = artifactFactory.createArtifactWithClassifier( artifact.getGroupId(),
 955  
                                                                                         artifact.getArtifactId(),
 956  
                                                                                         artifact.getVersion(),
 957  
                                                                                         artifact.getType(),
 958  
                                                                                         classifier );
 959  12
             String dstFilename = basePath.substring( 0, delIndex ) + '-' + classifier + ".jar";
 960  12
             File dstFile = new File( dstFilename );
 961  12
             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  12
             if ( !dstFile.exists() )
 965  
             {
 966  3
                 wagonManager.getArtifact( classifiedArtifact, remoteRepos );
 967  
             }
 968  9
             return dstFile.getAbsolutePath().replace( '\\', '/' );
 969  
         }
 970  0
         catch ( TransferFailedException e )
 971  
         {
 972  0
             getLog().debug( e );
 973  0
             return null;
 974  
         }
 975  3
         catch ( ResourceDoesNotExistException e )
 976  
         {
 977  3
             getLog().debug( e );
 978  3
             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  21
         return findElement( component, "setting", name );
 992  
     }
 993  
 
 994  
     private String getLibraryUrl( Artifact artifact )
 995  
     {
 996  246
         return "jar://" + convertDriveLetter( artifact.getFile().getAbsolutePath() ).replace( '\\', '/' ) + "!/";
 997  
     }
 998  
 
 999  
     private Element addDeploymentDescriptor( Element component, String name, String version, String file )
 1000  
     {
 1001  24
         Element deploymentDescriptor = findElement( component, "deploymentDescriptor" );
 1002  
 
 1003  24
         if ( deploymentDescriptor.attributeValue( "version" ) == null )
 1004  
         {
 1005  0
             deploymentDescriptor.addAttribute( "version", version );
 1006  
         }
 1007  
 
 1008  24
         if ( deploymentDescriptor.attributeValue( "name" ) == null )
 1009  
         {
 1010  0
             deploymentDescriptor.addAttribute( "name", name );
 1011  
         }
 1012  
 
 1013  24
         deploymentDescriptor.addAttribute( "optional", "false" );
 1014  
 
 1015  24
         if ( deploymentDescriptorFile == null )
 1016  
         {
 1017  21
             deploymentDescriptorFile = file;
 1018  
         }
 1019  
 
 1020  24
         deploymentDescriptor.addAttribute( "url", getModuleFileUrl( deploymentDescriptorFile ) );
 1021  
 
 1022  24
         return deploymentDescriptor;
 1023  
     }
 1024  
 }