Coverage Report - org.apache.maven.plugin.resources.remote.ProcessRemoteResourcesMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
ProcessRemoteResourcesMojo
40%
152/380
32%
55/170
0
ProcessRemoteResourcesMojo$OrganizationComparator
8%
1/13
0%
0/16
0
ProcessRemoteResourcesMojo$ProjectComparator
33%
1/3
N/A
0
 
 1  
 package org.apache.maven.plugin.resources.remote;
 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.ProjectDependenciesResolver;
 23  
 import org.apache.maven.artifact.Artifact;
 24  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 25  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 26  
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 27  
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 28  
 import org.apache.maven.artifact.versioning.VersionRange;
 29  
 import org.apache.maven.execution.MavenSession;
 30  
 import org.apache.maven.model.Model;
 31  
 import org.apache.maven.model.Organization;
 32  
 import org.apache.maven.model.Resource;
 33  
 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
 34  
 import org.apache.maven.plugin.AbstractMojo;
 35  
 import org.apache.maven.plugin.MojoExecutionException;
 36  
 import org.apache.maven.plugin.logging.Log;
 37  
 import org.apache.maven.plugin.resources.remote.io.xpp3.RemoteResourcesBundleXpp3Reader;
 38  
 import org.apache.maven.plugin.resources.remote.io.xpp3.SupplementalDataModelXpp3Reader;
 39  
 import org.apache.maven.project.InvalidProjectModelException;
 40  
 import org.apache.maven.project.MavenProject;
 41  
 import org.apache.maven.project.MavenProjectBuilder;
 42  
 import org.apache.maven.project.ProjectBuildingException;
 43  
 import org.apache.maven.project.artifact.InvalidDependencyVersionException;
 44  
 import org.apache.maven.project.inheritance.ModelInheritanceAssembler;
 45  
 import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
 46  
 import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
 47  
 import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
 48  
 import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
 49  
 import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
 50  
 import org.apache.maven.shared.artifact.filter.collection.TransitivityFilter;
 51  
 import org.apache.maven.shared.downloader.DownloadException;
 52  
 import org.apache.maven.shared.downloader.DownloadNotFoundException;
 53  
 import org.apache.maven.shared.downloader.Downloader;
 54  
 import org.apache.maven.shared.filtering.MavenFileFilter;
 55  
 import org.apache.maven.shared.filtering.MavenFileFilterRequest;
 56  
 import org.apache.maven.shared.filtering.MavenFilteringException;
 57  
 import org.apache.velocity.VelocityContext;
 58  
 import org.apache.velocity.app.Velocity;
 59  
 import org.apache.velocity.exception.MethodInvocationException;
 60  
 import org.apache.velocity.exception.ParseErrorException;
 61  
 import org.apache.velocity.exception.ResourceNotFoundException;
 62  
 import org.codehaus.plexus.resource.ResourceManager;
 63  
 import org.codehaus.plexus.resource.loader.FileResourceLoader;
 64  
 import org.codehaus.plexus.util.FileUtils;
 65  
 import org.codehaus.plexus.util.IOUtil;
 66  
 import org.codehaus.plexus.util.ReaderFactory;
 67  
 import org.codehaus.plexus.util.StringUtils;
 68  
 import org.codehaus.plexus.util.WriterFactory;
 69  
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 70  
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 71  
 import org.codehaus.plexus.velocity.VelocityComponent;
 72  
 
 73  
 import java.io.File;
 74  
 import java.io.FileInputStream;
 75  
 import java.io.FileOutputStream;
 76  
 import java.io.FileReader;
 77  
 import java.io.FileWriter;
 78  
 import java.io.IOException;
 79  
 import java.io.InputStream;
 80  
 import java.io.InputStreamReader;
 81  
 import java.io.OutputStream;
 82  
 import java.io.OutputStreamWriter;
 83  
 import java.io.PrintWriter;
 84  
 import java.io.Reader;
 85  
 import java.io.StringReader;
 86  
 import java.io.Writer;
 87  
 import java.net.MalformedURLException;
 88  
 import java.net.URL;
 89  
 import java.text.SimpleDateFormat;
 90  
 import java.util.ArrayList;
 91  
 import java.util.Collections;
 92  
 import java.util.Comparator;
 93  
 import java.util.Date;
 94  
 import java.util.Enumeration;
 95  
 import java.util.HashMap;
 96  
 import java.util.LinkedHashSet;
 97  
 import java.util.List;
 98  
 import java.util.Map;
 99  
 import java.util.Properties;
 100  
 import java.util.Set;
 101  
 import java.util.TreeMap;
 102  
 
 103  
 /**
 104  
  * <p>
 105  
  * Pull down resourceBundles containing remote resources and process the
 106  
  * resources contained inside. When that is done the resources are injected
 107  
  * into the current (in-memory) Maven project, making them available to the
 108  
  * process-resources phase.
 109  
  * </p>
 110  
  * <p>
 111  
  * Resources that end in ".vm" are treated as velocity templates.  For those, the ".vm" is
 112  
  * stripped off for the final artifact name and it's  fed through velocity to have properties
 113  
  * expanded, conditions processed, etc...
 114  
  * </p>
 115  
  * <p>
 116  
  * Resources that don't end in ".vm" are copied "as is".
 117  
  * </p>
 118  
  *
 119  
  * @goal process
 120  
  * @phase generate-resources
 121  
  * @threadSafe
 122  
  */
 123  
 // NOTE: Removed the following in favor of maven-artifact-resolver library, for MRRESOURCES-41
 124  
 // If I leave this intact, interdependent projects within the reactor that haven't been built
 125  
 // (remember, this runs in the generate-resources phase) will cause the build to fail.
 126  
 //
 127  
 // @requiresDependencyResolution test
 128  7
 public class ProcessRemoteResourcesMojo
 129  
     extends AbstractMojo
 130  
 {
 131  
     
 132  
     private static final String TEMPLATE_SUFFIX = ".vm";
 133  
     
 134  
     /**
 135  
      * <p>
 136  
      * In cases where a local resource overrides one from a remote resource bundle, that resource
 137  
      * should be filtered if the resource set specifies it. In those cases, this parameter defines
 138  
      * the list of delimiters for filterable expressions. These delimiters are specified in the
 139  
      * form 'beginToken*endToken'. If no '*' is given, the delimiter is assumed to be the same for start and end.
 140  
      * </p>
 141  
      * <p>
 142  
      * So, the default filtering delimiters might be specified as:
 143  
      * </p>
 144  
      * <pre>
 145  
      * &lt;delimiters&gt;
 146  
      *   &lt;delimiter&gt;${*}&lt/delimiter&gt;
 147  
      *   &lt;delimiter&gt;@&lt/delimiter&gt;
 148  
      * &lt;/delimiters&gt;
 149  
      * </pre>
 150  
      * <p>
 151  
      * Since the '@' delimiter is the same on both ends, we don't need to specify '@*@' (though we can).
 152  
      * </p>
 153  
      * @parameter
 154  
      * @since 1.1
 155  
      */
 156  
     protected List<String> filterDelimiters;
 157  
 
 158  
     /**
 159  
      * @parameter default-value="true"
 160  
      * @since 1.1
 161  
      */
 162  
     protected boolean useDefaultFilterDelimiters;
 163  
     
 164  
     /**
 165  
      * If true, only generate resources in the directory of the root project in a multimodule build.
 166  
      * Dependencies from all modules will be aggregated before resource-generation takes place.
 167  
      * 
 168  
      * @parameter default-value="false"
 169  
      * @since 1.1
 170  
      */
 171  
     protected boolean runOnlyAtExecutionRoot;
 172  
     
 173  
     /**
 174  
      * Used for calculation of execution-root for {@link ProcessRemoteResourcesMojo#runOnlyAtExecutionRoot}.
 175  
      * 
 176  
      * @parameter default-value="${basedir}"
 177  
      * @readonly
 178  
      * @required
 179  
      */
 180  
     protected File basedir;
 181  
     
 182  
     /**
 183  
      * The character encoding scheme to be applied when filtering resources.
 184  
      *
 185  
      * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
 186  
      */
 187  
     protected String encoding;
 188  
 
 189  
     /**
 190  
      * The local repository taken from Maven's runtime. Typically $HOME/.m2/repository.
 191  
      *
 192  
      * @parameter expression="${localRepository}"
 193  
      * @readonly
 194  
      * @required
 195  
      */
 196  
     private ArtifactRepository localRepository;
 197  
 
 198  
     /**
 199  
      * List of Remote Repositories used by the resolver
 200  
      *
 201  
      * @parameter expression="${project.remoteArtifactRepositories}"
 202  
      * @readonly
 203  
      * @required
 204  
      */
 205  
     private List<ArtifactRepository> remoteArtifactRepositories;
 206  
 
 207  
     /**
 208  
      * The current Maven project.
 209  
      *
 210  
      * @parameter expression="${project}"
 211  
      * @readonly
 212  
      * @required
 213  
      */
 214  
     private MavenProject project;
 215  
 
 216  
     /**
 217  
      * The directory where processed resources will be placed for packaging.
 218  
      *
 219  
      * @parameter expression="${project.build.directory}/maven-shared-archive-resources"
 220  
      */
 221  
     private File outputDirectory;
 222  
 
 223  
     /**
 224  
      * The directory containing extra information appended to the generated resources.
 225  
      *
 226  
      * @parameter expression="${basedir}/src/main/appended-resources"
 227  
      */
 228  
     private File appendedResourcesDirectory;
 229  
 
 230  
     /**
 231  
      * Supplemental model data.  Useful when processing
 232  
      * artifacts with incomplete POM metadata.
 233  
      * <p/>
 234  
      * By default, this Mojo looks for supplemental model
 235  
      * data in the file "${appendedResourcesDirectory}/supplemental-models.xml".
 236  
      *
 237  
      * @parameter
 238  
      * @since 1.0-alpha-5
 239  
      */
 240  
     private String[] supplementalModels;
 241  
 
 242  
     /**
 243  
      * List of artifacts that are added to the search path when looking 
 244  
      * for supplementalModels
 245  
      * @parameter
 246  
      * @since 1.1 
 247  
      */
 248  
     private List<String> supplementalModelArtifacts;
 249  
 
 250  
     /**
 251  
      * Map of artifacts to supplemental project object models.
 252  
      */
 253  
     private Map<String, Model> supplementModels;
 254  
     
 255  
     /**
 256  
      * Merges supplemental data model with artifact
 257  
      * metadata.  Useful when processing artifacts with
 258  
      * incomplete POM metadata.
 259  
      *
 260  
      * @component
 261  
      * @readonly
 262  
      * @required
 263  
      */
 264  
     private ModelInheritanceAssembler inheritanceAssembler;
 265  
 
 266  
     /**
 267  
      * The resource bundles that will be retrieved and processed.
 268  
      *
 269  
      * @parameter
 270  
      * @required
 271  
      */
 272  
     private List<String> resourceBundles;
 273  
 
 274  
     /**
 275  
      * Skip remote-resource processing
 276  
      *
 277  
      * @parameter expression="${remoteresources.skip}" default-value="false"
 278  
      * @since 1.0-alpha-5
 279  
      */
 280  
     private boolean skip;
 281  
 
 282  
     /**
 283  
      * Attaches the resource to the project as a resource directory
 284  
      *
 285  
      * @parameter default-value="true"
 286  
      * @since 1.0-beta-1
 287  
      */
 288  7
     private boolean attached = true;
 289  
 
 290  
     /**
 291  
      * Additional properties to be passed to velocity.
 292  
      * <p/>
 293  
      * Several properties are automatically added:<br/>
 294  
      * project - the current MavenProject <br/>
 295  
      * projects - the list of dependency projects<br/>
 296  
      * projectTimespan - the timespan of the current project (requires inceptionYear in pom)<br/>
 297  
      * <p/>
 298  
      * See <a href="http://maven.apache.org/ref/current/maven-project/apidocs/org/apache/maven/project/MavenProject.html">
 299  
      * the javadoc for MavenProject</a> for information about the properties on the MavenProject.
 300  
      *
 301  
      * @parameter
 302  
      */
 303  7
     private Map<String, String> properties = new HashMap<String, String>();
 304  
 
 305  
     /**
 306  
      * Whether to include properties defined in the project when filtering resources.
 307  
      *
 308  
      * @parameter default-value="false"
 309  
      * @since 1.2
 310  
      */
 311  7
     protected boolean includeProjectProperties = false;
 312  
     
 313  
     /**
 314  
      * The list of resources defined for the project.
 315  
      *
 316  
      * @parameter expression="${project.resources}"
 317  
      * @readonly
 318  
      * @required
 319  
      */
 320  
     private List<Resource> resources;
 321  
 
 322  
     /**
 323  
      * Artifact downloader.
 324  
      *
 325  
      * @component
 326  
      * @readonly
 327  
      * @required
 328  
      */
 329  
     private Downloader downloader;
 330  
 
 331  
     /**
 332  
      * Velocity component.
 333  
      *
 334  
      * @component
 335  
      * @readonly
 336  
      * @required
 337  
      */
 338  
     private VelocityComponent velocity;
 339  
     
 340  
     /**
 341  
      * Filtering support, for local resources that override those in the remote bundle.
 342  
      * 
 343  
      * @component
 344  
      */
 345  
     private MavenFileFilter fileFilter;
 346  
 
 347  
     /**
 348  
      * Artifact factory, needed to create artifacts.
 349  
      *
 350  
      * @component
 351  
      * @readonly
 352  
      * @required
 353  
      */
 354  
     private ArtifactFactory artifactFactory;
 355  
 
 356  
     /**
 357  
      * The Maven session.
 358  
      *
 359  
      * @parameter expression="${session}"
 360  
      * @readonly
 361  
      * @required
 362  
      */
 363  
     private MavenSession mavenSession;
 364  
 
 365  
     /**
 366  
      * ProjectBuilder, needed to create projects from the artifacts.
 367  
      *
 368  
      * @component role="org.apache.maven.project.MavenProjectBuilder"
 369  
      * @required
 370  
      * @readonly
 371  
      */
 372  
     private MavenProjectBuilder mavenProjectBuilder;
 373  
 
 374  
     /**
 375  
      * @component
 376  
      * @required
 377  
      * @readonly
 378  
      */
 379  
     private ResourceManager locator;
 380  
 
 381  
 
 382  
     /**
 383  
      * Scope to include. An Empty string indicates all scopes (default).
 384  
      *
 385  
      * @since 1.0
 386  
      * @parameter expression="${includeScope}" default-value="runtime"
 387  
      * @optional
 388  
      */
 389  
     protected String includeScope;
 390  
 
 391  
     /**
 392  
      * Scope to exclude. An Empty string indicates no scopes (default).
 393  
      *
 394  
      * @since 1.0
 395  
      * @parameter expression="${excludeScope}" default-value=""
 396  
      * @optional
 397  
      */
 398  
     protected String excludeScope;
 399  
 
 400  
     /**
 401  
      * Comma separated list of Artifact names too exclude.
 402  
      *
 403  
      * @since 1.0
 404  
      * @optional
 405  
      * @parameter expression="${excludeArtifactIds}" default-value=""
 406  
      */
 407  
     protected String excludeArtifactIds;
 408  
 
 409  
     /**
 410  
      * Comma separated list of Artifact names to include.
 411  
      *
 412  
      * @since 1.0
 413  
      * @optional
 414  
      * @parameter expression="${includeArtifactIds}" default-value=""
 415  
      */
 416  
     protected String includeArtifactIds;
 417  
 
 418  
     /**
 419  
      * Comma separated list of GroupId Names to exclude.
 420  
      *
 421  
      * @since 1.0
 422  
      * @optional
 423  
      * @parameter expression="${excludeGroupIds}" default-value=""
 424  
      */
 425  
     protected String excludeGroupIds;
 426  
 
 427  
     /**
 428  
      * Comma separated list of GroupIds to include.
 429  
      *
 430  
      * @since 1.0
 431  
      * @optional
 432  
      * @parameter expression="${includeGroupIds}" default-value=""
 433  
      */
 434  
     protected String includeGroupIds;
 435  
 
 436  
     /**
 437  
      * If we should exclude transitive dependencies
 438  
      *
 439  
      * @since 1.0
 440  
      * @optional
 441  
      * @parameter expression="${excludeTransitive}" default-value="false"
 442  
      */
 443  
     protected boolean excludeTransitive;
 444  
     
 445  
     /**
 446  
      * @component role-hint="default"
 447  
      */
 448  
     protected ProjectDependenciesResolver dependencyResolver;
 449  
 
 450  
     @SuppressWarnings( "unchecked" )
 451  
     public void execute()
 452  
         throws MojoExecutionException
 453  
     {
 454  8
         if ( skip )
 455  
         {
 456  0
             return;
 457  
         }
 458  
         
 459  8
         if ( runOnlyAtExecutionRoot && !isExecutionRoot() )
 460  
         {
 461  0
             getLog().info( "Skipping remote-resource generation in this project because it's not the Execution Root" );
 462  0
             return;
 463  
         }
 464  
         
 465  8
         if ( supplementalModels == null )
 466  
         {
 467  8
             File sups = new File( appendedResourcesDirectory, "supplemental-models.xml" );
 468  8
             if ( sups.exists() )
 469  
             {
 470  
                 try
 471  
                 {
 472  0
                     supplementalModels = new String[]{sups.toURL().toString()};
 473  
                 }
 474  0
                 catch ( MalformedURLException e )
 475  
                 {
 476  
                     //ignore
 477  0
                     getLog().debug( "URL issue with supplemental-models.xml: " + e.toString() );
 478  0
                 }
 479  
             }
 480  
         }
 481  
 
 482  8
         addSupplementalModelArtifacts();
 483  8
         locator.addSearchPath( FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath() );
 484  8
         if ( appendedResourcesDirectory != null )
 485  
         {
 486  0
             locator.addSearchPath( FileResourceLoader.ID, appendedResourcesDirectory.getAbsolutePath() );
 487  
         }
 488  8
         locator.addSearchPath( "url", "" );
 489  8
         locator.setOutputDirectory( new File( project.getBuild().getDirectory() ) );
 490  
 
 491  8
         if ( includeProjectProperties )
 492  
         {
 493  2
             final Properties projectProperties = project.getProperties();
 494  2
             for ( Object key : projectProperties.keySet() )
 495  
             {
 496  4
                 properties.put( key.toString(), projectProperties.get( key ).toString() );
 497  
             }
 498  
         }
 499  
 
 500  8
         ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
 501  
         try
 502  
         {
 503  8
             Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() );
 504  
 
 505  8
             validate();
 506  
 
 507  8
             List<File> resourceBundleArtifacts = downloadBundles( resourceBundles );
 508  8
             supplementModels = loadSupplements( supplementalModels );
 509  
 
 510  8
             VelocityContext context = new VelocityContext( properties );
 511  8
             configureVelocityContext( context );
 512  
 
 513  8
             RemoteResourcesClassLoader classLoader
 514  
                 = new RemoteResourcesClassLoader( null );
 515  
             
 516  8
             initalizeClassloader( classLoader, resourceBundleArtifacts );
 517  8
             Thread.currentThread().setContextClassLoader( classLoader );
 518  
             
 519  8
             processResourceBundles( classLoader, context );
 520  
 
 521  
             try
 522  
             {
 523  8
                 if ( outputDirectory.exists() )
 524  
                 {
 525  
                     // ----------------------------------------------------------------------------
 526  
                     // Push our newly generated resources directory into the MavenProject so that
 527  
                     // these resources can be picked up by the process-resources phase.
 528  
                     // ----------------------------------------------------------------------------
 529  8
                     if ( attached )
 530  
                     {
 531  8
                         Resource resource = new Resource();
 532  8
                         resource.setDirectory( outputDirectory.getAbsolutePath() );
 533  
 
 534  8
                         project.getResources().add( resource );
 535  8
                         project.getTestResources().add( resource );
 536  
                     }
 537  
 
 538  
                     // ----------------------------------------------------------------------------
 539  
                     // Write out archiver dot file
 540  
                     // ----------------------------------------------------------------------------
 541  8
                     File dotFile = new File( project.getBuild().getDirectory(), ".plxarc" );
 542  8
                     FileUtils.mkdir( dotFile.getParentFile().getAbsolutePath() );
 543  8
                     FileUtils.fileWrite( dotFile.getAbsolutePath(), outputDirectory.getName() );
 544  
                 }
 545  
             }
 546  0
             catch ( IOException e )
 547  
             {
 548  0
                 throw new MojoExecutionException( "Error creating dot file for archiving instructions.", e );
 549  8
             }
 550  
         }
 551  
         finally
 552  
         {
 553  8
             Thread.currentThread().setContextClassLoader( origLoader );
 554  8
         }
 555  8
     }
 556  
 
 557  
     private boolean isExecutionRoot()
 558  
     {
 559  0
         Log log = this.getLog();
 560  
         
 561  0
         boolean result = mavenSession.getExecutionRootDirectory().equalsIgnoreCase( basedir.toString() );
 562  
         
 563  0
         if ( log.isDebugEnabled() )
 564  
         {
 565  0
             log.debug("Root Folder:" + mavenSession.getExecutionRootDirectory());
 566  0
             log.debug("Current Folder:"+ basedir );
 567  
             
 568  0
             if ( result )
 569  
             {
 570  0
                 log.debug( "This is the execution root." );
 571  
             }
 572  
             else
 573  
             {
 574  0
                 log.debug( "This is NOT the execution root." );
 575  
             }
 576  
         }
 577  
         
 578  0
         return result;
 579  
     }
 580  
 
 581  
     private void addSupplementalModelArtifacts() throws MojoExecutionException
 582  
     {
 583  8
         if ( supplementalModelArtifacts != null && !supplementalModelArtifacts.isEmpty() )
 584  
         {
 585  0
             List<File> artifacts = downloadBundles( supplementalModelArtifacts );
 586  
             
 587  0
             for ( File artifact : artifacts )
 588  
             {
 589  0
                 if ( artifact.isDirectory() ) 
 590  
                 {
 591  0
                     locator.addSearchPath( FileResourceLoader.ID, artifact.getAbsolutePath() );
 592  
                 }
 593  
                 else
 594  
                 {
 595  
                     try 
 596  
                     {
 597  0
                         locator.addSearchPath( "jar", "jar:" + artifact.toURL().toExternalForm() );
 598  
                     } 
 599  0
                     catch (MalformedURLException e) 
 600  
                     {
 601  0
                         throw new MojoExecutionException( "Could not use jar " 
 602  
                                                           + artifact.getAbsolutePath(), e );
 603  0
                     }
 604  
                 }
 605  
             }
 606  
 
 607  
             
 608  
         }
 609  8
     }
 610  
 
 611  
     @SuppressWarnings( "unchecked" )
 612  
     protected List<MavenProject> getProjects()
 613  
         throws MojoExecutionException
 614  
     {
 615  8
         List<MavenProject> projects = new ArrayList<MavenProject>();
 616  
 
 617  
         // add filters in well known order, least specific to most specific
 618  8
         FilterArtifacts filter = new FilterArtifacts();
 619  
         
 620  
         Set<Artifact> depArtifacts;
 621  8
         Set<Artifact> artifacts = resolveProjectArtifacts();
 622  8
         if ( runOnlyAtExecutionRoot )
 623  
         {
 624  0
             depArtifacts = aggregateProjectDependencyArtifacts();
 625  
         }
 626  
         else
 627  
         {
 628  8
             depArtifacts = project.getDependencyArtifacts();
 629  
         }
 630  
 
 631  8
         filter.addFilter( new TransitivityFilter( depArtifacts, this.excludeTransitive ) );
 632  8
         filter.addFilter( new ScopeFilter( this.includeScope, this.excludeScope ) );
 633  8
         filter.addFilter( new GroupIdFilter( this.includeGroupIds, this.excludeGroupIds ) );
 634  8
         filter.addFilter( new ArtifactIdFilter( this.includeArtifactIds, this.excludeArtifactIds ) );
 635  
 
 636  
         // perform filtering
 637  
         try
 638  
         {
 639  8
             artifacts = filter.filter( artifacts );
 640  
         }
 641  0
         catch ( ArtifactFilterException e )
 642  
         {
 643  0
             throw new MojoExecutionException(e.getMessage(),e);
 644  8
         }
 645  
 
 646  
 
 647  8
         for ( Artifact artifact : artifacts )
 648  
         {
 649  
             try
 650  
             {
 651  0
                 List<ArtifactRepository> remoteRepo = remoteArtifactRepositories;
 652  0
                 if ( artifact.isSnapshot() )
 653  
                 {
 654  0
                     VersionRange rng = VersionRange.createFromVersion( artifact.getBaseVersion() );
 655  0
                     artifact = artifactFactory.createDependencyArtifact( artifact.getGroupId(),
 656  
                                                                          artifact.getArtifactId(), rng,
 657  
                                                                          artifact.getType(), artifact.getClassifier(),
 658  
                                                                          artifact.getScope(), null,
 659  
                                                                          artifact.isOptional() );
 660  
                 }
 661  
 
 662  0
                 getLog().debug( "Building project for " + artifact );
 663  0
                 MavenProject p = null;
 664  
                 try
 665  
                 {
 666  0
                     p = mavenProjectBuilder.buildFromRepository( artifact, remoteRepo, localRepository );
 667  
                 }
 668  0
                 catch ( InvalidProjectModelException e )
 669  
                 {
 670  0
                     getLog().warn( "Invalid project model for artifact [" + artifact.getArtifactId() + ":" +
 671  
                         artifact.getGroupId() + ":" + artifact.getVersion() + "]. " +
 672  
                         "It will be ignored by the remote resources Mojo." );
 673  0
                     continue;
 674  0
                 }
 675  
 
 676  0
                 String supplementKey =
 677  
                     generateSupplementMapKey( p.getModel().getGroupId(), p.getModel().getArtifactId() );
 678  
 
 679  0
                 if ( supplementModels.containsKey( supplementKey ) )
 680  
                 {
 681  0
                     Model mergedModel = mergeModels( p.getModel(), (Model) supplementModels.get( supplementKey ) );
 682  0
                     MavenProject mergedProject = new MavenProject( mergedModel );
 683  0
                     projects.add( mergedProject );
 684  0
                     mergedProject.setArtifact( artifact );
 685  0
                     mergedProject.setVersion( artifact.getVersion() );
 686  0
                     getLog().debug( "Adding project with groupId [" + mergedProject.getGroupId() + "] (supplemented)" );
 687  0
                 }
 688  
                 else
 689  
                 {
 690  0
                     projects.add( p );
 691  0
                     getLog().debug( "Adding project with groupId [" + p.getGroupId() + "]" );
 692  
                 }
 693  
             }
 694  0
             catch ( ProjectBuildingException e )
 695  
             {
 696  0
                 throw new MojoExecutionException( e.getMessage(), e );
 697  0
             }
 698  
         }
 699  8
         Collections.sort( projects, new ProjectComparator() );
 700  8
         return projects;
 701  
     }
 702  
 
 703  
     @SuppressWarnings( "unchecked" )
 704  
     private Set<Artifact> resolveProjectArtifacts()
 705  
         throws MojoExecutionException
 706  
     {
 707  
         try
 708  
         {
 709  8
             if ( runOnlyAtExecutionRoot )
 710  
             {
 711  0
                 List<MavenProject> projects = mavenSession.getSortedProjects();
 712  0
                 return dependencyResolver.resolve( projects, Collections.singleton( Artifact.SCOPE_TEST ), mavenSession );
 713  
             }
 714  
             else
 715  
             {
 716  8
                 return dependencyResolver.resolve( project, Collections.singleton( Artifact.SCOPE_TEST ), mavenSession );
 717  
             }
 718  
         }
 719  0
         catch ( ArtifactResolutionException e )
 720  
         {
 721  0
             throw new MojoExecutionException( "Failed to resolve dependencies for one or more projects in the reactor. Reason: "
 722  
                 + e.getMessage(), e );
 723  
         }
 724  0
         catch ( ArtifactNotFoundException e )
 725  
         {
 726  0
             throw new MojoExecutionException( "Failed to resolve dependencies for one or more projects in the reactor. Reason: "
 727  
                 + e.getMessage(), e );
 728  
         }
 729  
     }
 730  
 
 731  
     @SuppressWarnings( "unchecked" )
 732  
     private Set<Artifact> aggregateProjectDependencyArtifacts()
 733  
         throws MojoExecutionException
 734  
     {
 735  0
         Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
 736  
         
 737  0
         List<MavenProject> projects = mavenSession.getSortedProjects();
 738  0
         for ( MavenProject p : projects )
 739  
         {
 740  0
             if ( p.getDependencyArtifacts() == null )
 741  
             {
 742  
                 try
 743  
                 {
 744  0
                     Set<Artifact> depArtifacts = p.createArtifacts( artifactFactory, null, null );
 745  0
                     p.setDependencyArtifacts( depArtifacts );
 746  
                     
 747  0
                     if ( depArtifacts != null && !depArtifacts.isEmpty() )
 748  
                     {
 749  0
                         artifacts.addAll( depArtifacts );
 750  
                     }
 751  
                 }
 752  0
                 catch ( InvalidDependencyVersionException e )
 753  
                 {
 754  0
                     throw new MojoExecutionException( "Failed to create dependency artifacts for: " + p.getId() + ". Reason: "
 755  
                         + e.getMessage(), e );
 756  0
                 }
 757  
             }
 758  
         }
 759  
         
 760  0
         return artifacts;
 761  
     }
 762  
 
 763  
     protected Map<Organization, List<MavenProject>> getProjectsSortedByOrganization( List<MavenProject> projects )
 764  
         throws MojoExecutionException
 765  
     {
 766  8
         Map<Organization, List<MavenProject>> organizations = new TreeMap<Organization, List<MavenProject>>( new OrganizationComparator() );
 767  8
         List<MavenProject> unknownOrganization = new ArrayList<MavenProject>();
 768  
 
 769  8
         for ( MavenProject p : projects )
 770  
         {
 771  0
             if ( p.getOrganization() != null && StringUtils.isNotEmpty( p.getOrganization().getName() ) )
 772  
             {
 773  0
                 List<MavenProject> sortedProjects = (List<MavenProject>) organizations.get( p.getOrganization() );
 774  0
                 if ( sortedProjects == null )
 775  
                 {
 776  0
                     sortedProjects = new ArrayList<MavenProject>();
 777  
                 }
 778  0
                 sortedProjects.add( p );
 779  
 
 780  0
                 organizations.put( p.getOrganization(), sortedProjects );
 781  0
             }
 782  
             else
 783  
             {
 784  0
                 unknownOrganization.add( p );
 785  
             }
 786  
         }
 787  8
         if ( !unknownOrganization.isEmpty() )
 788  
         {
 789  0
             Organization unknownOrg = new Organization();
 790  0
             unknownOrg.setName( "an unknown organization" );
 791  0
             organizations.put( unknownOrg, unknownOrganization );
 792  
         }
 793  
 
 794  8
         return organizations;
 795  
     }
 796  
 
 797  
     protected boolean copyResourceIfExists( File file, String relFileName, VelocityContext context )
 798  
         throws IOException, MojoExecutionException
 799  
     {
 800  7
         for ( Resource resource : resources )
 801  
         {
 802  9
             File resourceDirectory = new File( resource.getDirectory() );
 803  
 
 804  9
             if ( !resourceDirectory.exists() )
 805  
             {
 806  0
                 continue;
 807  
             }
 808  
             
 809  
             //TODO - really should use the resource includes/excludes and name mapping
 810  9
             File source = new File( resourceDirectory, relFileName );
 811  9
             File templateSource = new File( resourceDirectory, relFileName + TEMPLATE_SUFFIX );
 812  
             
 813  9
             if ( !source.exists() && templateSource.exists() )
 814  
             {
 815  0
                 source = templateSource;
 816  
             }
 817  
 
 818  9
             if ( source.exists() && !source.equals( file ) )
 819  
             {
 820  0
                 if ( source == templateSource )
 821  
                 {
 822  0
                     Reader reader = null;
 823  0
                     Writer writer = null;
 824  
                     try
 825  
                     {
 826  0
                         if ( encoding != null )
 827  
                         {
 828  0
                             reader = new InputStreamReader( new FileInputStream( source ), encoding );
 829  0
                             writer = new OutputStreamWriter( new FileOutputStream( file ), encoding );
 830  
                         }
 831  
                         else
 832  
                         {
 833  0
                             reader = ReaderFactory.newPlatformReader( source );
 834  0
                             writer = WriterFactory.newPlatformWriter( file );
 835  
                         }
 836  
                         
 837  0
                         velocity.getEngine().evaluate( context, writer, "", reader );
 838  0
                         velocity.getEngine().evaluate( context, writer, "", reader );
 839  
                     }
 840  0
                     catch ( ParseErrorException e )
 841  
                     {
 842  0
                         throw new MojoExecutionException( "Error rendering velocity resource.", e );
 843  
                     }
 844  0
                     catch ( MethodInvocationException e )
 845  
                     {
 846  0
                         throw new MojoExecutionException( "Error rendering velocity resource.", e );
 847  
                     }
 848  0
                     catch ( ResourceNotFoundException e )
 849  
                     {
 850  0
                         throw new MojoExecutionException( "Error rendering velocity resource.", e );
 851  
                     }
 852  
                     finally
 853  
                     {
 854  0
                         IOUtil.close( writer );
 855  0
                         IOUtil.close( reader );
 856  0
                     }
 857  0
                 }
 858  0
                 else if ( resource.isFiltering() )
 859  
                 {
 860  
                     
 861  0
                     MavenFileFilterRequest req = setupRequest( resource, source, file );
 862  
                     
 863  
                     try
 864  
                     {
 865  0
                         fileFilter.copyFile( req );
 866  
                     }
 867  0
                     catch ( MavenFilteringException e )
 868  
                     {
 869  0
                         throw new MojoExecutionException( "Error filtering resource: " + source, e );
 870  0
                     }
 871  0
                 }
 872  
                 else
 873  
                 {
 874  0
                     FileUtils.copyFile( source, file );
 875  
                 }
 876  
 
 877  
                 //exclude the original (so eclipse doesn't complain about duplicate resources)
 878  0
                 resource.addExclude( relFileName );
 879  
 
 880  0
                 return true;
 881  
             }
 882  
 
 883  9
         }
 884  7
         return false;
 885  
     }
 886  
 
 887  
     @SuppressWarnings( "unchecked" )
 888  
     private MavenFileFilterRequest setupRequest( Resource resource, File source, File file )
 889  
     {
 890  0
         MavenFileFilterRequest req = new MavenFileFilterRequest();
 891  0
         req.setFrom( source );
 892  0
         req.setTo( file );
 893  0
         req.setFiltering( resource.isFiltering() );
 894  
         
 895  0
         req.setMavenProject( project );
 896  0
         req.setMavenSession( mavenSession );
 897  0
         req.setInjectProjectBuildFilters( true );
 898  
         
 899  0
         if ( encoding != null )
 900  
         {
 901  0
             req.setEncoding( encoding );
 902  
         }
 903  
         
 904  0
         if ( filterDelimiters != null && !filterDelimiters.isEmpty() )
 905  
         {
 906  0
             LinkedHashSet<String> delims = new LinkedHashSet<String>();
 907  0
             if ( useDefaultFilterDelimiters )
 908  
             {
 909  0
                 delims.addAll( req.getDelimiters() );
 910  
             }
 911  
             
 912  0
             for ( String delim : filterDelimiters )
 913  
             {
 914  0
                 if ( delim == null )
 915  
                 {
 916  0
                     delims.add( "${*}" );
 917  
                 }
 918  
                 else
 919  
                 {
 920  0
                     delims.add( delim );
 921  
                 }
 922  
             }
 923  
             
 924  0
             req.setDelimiters( delims );
 925  
         }
 926  
         
 927  0
         return req;
 928  
     }
 929  
 
 930  
     protected void validate()
 931  
         throws MojoExecutionException
 932  
     {
 933  8
         int bundleCount = 1;
 934  
 
 935  8
         for ( String artifactDescriptor : resourceBundles )
 936  
         {
 937  
             // groupId:artifactId:version
 938  7
             String[] s = StringUtils.split( artifactDescriptor, ":" );
 939  
 
 940  7
             if ( s.length != 3 )
 941  
             {
 942  
                 String position;
 943  
 
 944  0
                 if ( bundleCount == 1 )
 945  
                 {
 946  0
                     position = "1st";
 947  
                 }
 948  0
                 else if ( bundleCount == 2 )
 949  
                 {
 950  0
                     position = "2nd";
 951  
                 }
 952  0
                 else if ( bundleCount == 3 )
 953  
                 {
 954  0
                     position = "3rd";
 955  
                 }
 956  
                 else
 957  
                 {
 958  0
                     position = bundleCount + "th";
 959  
                 }
 960  
 
 961  0
                 throw new MojoExecutionException( "The " + position +
 962  
                     " resource bundle configured must specify a groupId, artifactId, and" +
 963  
                     " version for a remote resource bundle. " +
 964  
                     "Must be of the form <resourceBundle>groupId:artifactId:version</resourceBundle>" );
 965  
             }
 966  
 
 967  7
             bundleCount++;
 968  7
         }
 969  
 
 970  8
     }
 971  
 
 972  
     protected void configureVelocityContext( VelocityContext context )
 973  
         throws MojoExecutionException
 974  
     {
 975  8
         String inceptionYear = project.getInceptionYear();
 976  8
         String year = new SimpleDateFormat( "yyyy" ).format( new Date() );
 977  
 
 978  8
         if ( StringUtils.isEmpty( inceptionYear ) )
 979  
         {
 980  0
             if ( getLog().isDebugEnabled() )
 981  
             {
 982  0
                 getLog().debug( "inceptionYear not specified, defaulting to " + year );
 983  
             }
 984  
             
 985  0
             inceptionYear = year;
 986  
         }
 987  8
         context.put( "project", project );
 988  8
         List<MavenProject> projects = getProjects();
 989  8
         context.put( "projects", projects );
 990  8
         context.put( "projectsSortedByOrganization", getProjectsSortedByOrganization( projects ) );
 991  
 
 992  8
         context.put( "presentYear", year );
 993  
 
 994  8
         if ( inceptionYear.equals( year ) )
 995  
         {
 996  0
             context.put( "projectTimespan", year );
 997  
         }
 998  
         else
 999  
         {
 1000  8
             context.put( "projectTimespan", inceptionYear + "-" + year );
 1001  
         }
 1002  8
     }
 1003  
 
 1004  
     @SuppressWarnings( "unchecked" )
 1005  
     private List<File> downloadBundles( List<String> bundles )
 1006  
         throws MojoExecutionException
 1007  
     {
 1008  8
         List<File> bundleArtifacts = new ArrayList<File>();
 1009  
 
 1010  
         try
 1011  
         {
 1012  8
             for ( String artifactDescriptor : bundles )
 1013  
             {
 1014  
                 // groupId:artifactId:version
 1015  7
                 String[] s = artifactDescriptor.split( ":" );
 1016  7
                 File artifact = null;
 1017  
                 //check if the artifact is part of the reactor
 1018  7
                 if ( mavenSession != null ) 
 1019  
                 {
 1020  7
                     List<MavenProject> list = mavenSession.getSortedProjects();
 1021  7
                     for ( MavenProject p : list )
 1022  
                     {
 1023  0
                         if ( s[0].equals( p.getGroupId() )
 1024  
                             && s[1].equals( p.getArtifactId() ) 
 1025  
                             && s[2].equals( p.getVersion() ) ) 
 1026  
                         {
 1027  0
                             artifact = new File( p.getBuild().getOutputDirectory() );
 1028  
                         }
 1029  
                     }
 1030  
                 }
 1031  7
                 if ( artifact == null || !artifact.exists() )
 1032  
                 {
 1033  7
                     artifact = downloader.download( s[0], s[1], s[2], localRepository, remoteArtifactRepositories );
 1034  
                 }
 1035  
 
 1036  7
                 bundleArtifacts.add( artifact );
 1037  7
             }
 1038  
         }
 1039  0
         catch ( DownloadException e )
 1040  
         {
 1041  0
             throw new MojoExecutionException( "Error downloading resources JAR.", e );
 1042  
         }
 1043  0
         catch ( DownloadNotFoundException e )
 1044  
         {
 1045  0
             throw new MojoExecutionException( "Resources JAR cannot be found.", e );
 1046  8
         }
 1047  
 
 1048  8
         return bundleArtifacts;
 1049  
     }
 1050  
 
 1051  
     private void initalizeClassloader( RemoteResourcesClassLoader cl, List<File> artifacts )
 1052  
         throws MojoExecutionException
 1053  
     {
 1054  
         try
 1055  
         {
 1056  8
             for ( File artifact : artifacts )
 1057  
             {
 1058  7
                 cl.addURL( artifact.toURI().toURL() );
 1059  
             }
 1060  
         }
 1061  0
         catch ( MalformedURLException e )
 1062  
         {
 1063  0
             throw new MojoExecutionException( "Unable to configure resources classloader: " + e.getMessage(), e );
 1064  8
         }
 1065  8
     }
 1066  
 
 1067  
     protected void processResourceBundles( RemoteResourcesClassLoader classLoader, VelocityContext context )
 1068  
         throws MojoExecutionException
 1069  
     {
 1070  8
         InputStreamReader reader = null;
 1071  
         
 1072  
         try
 1073  
         {
 1074  
 
 1075  8
             for ( Enumeration<URL> e = classLoader.getResources( BundleRemoteResourcesMojo.RESOURCES_MANIFEST );
 1076  15
                   e.hasMoreElements(); )
 1077  
             {
 1078  7
                 URL url = (URL) e.nextElement();
 1079  
 
 1080  
                 try
 1081  
                 {
 1082  7
                     reader = new InputStreamReader( url.openStream() );
 1083  
 
 1084  7
                     RemoteResourcesBundleXpp3Reader bundleReader = new RemoteResourcesBundleXpp3Reader();
 1085  
 
 1086  7
                     RemoteResourcesBundle bundle = bundleReader.read( reader );
 1087  
 
 1088  7
                     for ( String bundleResource : (List<String>) bundle.getRemoteResources() )
 1089  
                     {
 1090  7
                         String projectResource = bundleResource;
 1091  
 
 1092  7
                         boolean doVelocity = false;
 1093  7
                         if ( projectResource.endsWith( TEMPLATE_SUFFIX ) )
 1094  
                         {
 1095  6
                             projectResource = projectResource.substring( 0, projectResource.length() - 3 );
 1096  6
                             doVelocity = true;
 1097  
                         }
 1098  
 
 1099  
                         // Don't overwrite resource that are already being provided.
 1100  
 
 1101  7
                         File f = new File( outputDirectory, projectResource );
 1102  
 
 1103  7
                         FileUtils.mkdir( f.getParentFile().getAbsolutePath() );
 1104  
 
 1105  7
                         if ( !copyResourceIfExists( f, projectResource, context ) )
 1106  
                         {
 1107  7
                             if ( doVelocity )
 1108  
                             {
 1109  
                                 PrintWriter writer;
 1110  6
                                 if ( bundle.getSourceEncoding() == null )
 1111  
                                 {
 1112  4
                                     writer = new PrintWriter( new FileWriter( f ) );
 1113  
                                 }
 1114  
                                 else
 1115  
                                 {
 1116  2
                                     writer = new PrintWriter( new OutputStreamWriter( new FileOutputStream( f ),
 1117  
                                                                                       bundle.getSourceEncoding() ) );
 1118  
 
 1119  
                                 }
 1120  
 
 1121  
                                 try
 1122  
                                 {
 1123  6
                                     if ( bundle.getSourceEncoding() == null )
 1124  
                                     {
 1125  4
                                         velocity.getEngine().mergeTemplate( bundleResource, context, writer );
 1126  
                                     }
 1127  
                                     else
 1128  
                                     {
 1129  2
                                         velocity.getEngine().mergeTemplate( bundleResource, bundle.getSourceEncoding(),
 1130  
                                                                             context, writer );
 1131  
 
 1132  
                                     }
 1133  
                                 }
 1134  
                                 finally
 1135  
                                 {
 1136  6
                                     IOUtil.close(writer);
 1137  6
                                 }
 1138  6
                             }
 1139  
                             else
 1140  
                             {
 1141  1
                                 URL resUrl = classLoader.getResource( bundleResource );
 1142  1
                                 if ( resUrl != null )
 1143  
                                 {
 1144  1
                                     FileUtils.copyURLToFile( resUrl, f );
 1145  
                                 }
 1146  
                             }
 1147  7
                             File appendedResourceFile = new File( appendedResourcesDirectory, projectResource );
 1148  7
                             File appendedVmResourceFile = new File( appendedResourcesDirectory,
 1149  
                                                                     projectResource + ".vm" );
 1150  7
                             if ( appendedResourceFile.exists() )
 1151  
                             {
 1152  0
                                 final InputStream in = new FileInputStream( appendedResourceFile );
 1153  0
                                 final OutputStream append = new FileOutputStream( f, true );
 1154  
 
 1155  
                                 try
 1156  
                                 {
 1157  0
                                     IOUtil.copy( in, append );
 1158  
                                 }
 1159  
                                 finally
 1160  
                                 {
 1161  0
                                     IOUtil.close( in );
 1162  0
                                     IOUtil.close( append );
 1163  0
                                 }
 1164  0
                             }
 1165  7
                             else if ( appendedVmResourceFile.exists() )
 1166  
                             {
 1167  
                                 PrintWriter writer;
 1168  0
                                 FileReader freader = new FileReader( appendedVmResourceFile );
 1169  
 
 1170  0
                                 if ( bundle.getSourceEncoding() == null )
 1171  
                                 {
 1172  0
                                     writer = new PrintWriter( new FileWriter( f, true ) );
 1173  
                                 }
 1174  
                                 else
 1175  
                                 {
 1176  0
                                     writer = new PrintWriter( new OutputStreamWriter( new FileOutputStream( f, true ),
 1177  
                                                                                       bundle.getSourceEncoding() ) );
 1178  
 
 1179  
                                 }
 1180  
 
 1181  
                                 try
 1182  
                                 {
 1183  0
                                     Velocity.init();
 1184  0
                                     Velocity.evaluate( context, writer, "remote-resources", freader );
 1185  
                                 }
 1186  
                                 finally
 1187  
                                 {
 1188  0
                                     IOUtil.close(writer);
 1189  0
                                     IOUtil.close(freader);
 1190  0
                                 }
 1191  
                             }
 1192  
 
 1193  
                         }
 1194  7
                     }
 1195  
                 }
 1196  
                 finally
 1197  
                 {
 1198  7
                     reader.close();
 1199  7
                 }
 1200  7
             }
 1201  
         }
 1202  0
         catch ( IOException e )
 1203  
         {
 1204  0
             throw new MojoExecutionException( "Error finding remote resources manifests", e );
 1205  
         }
 1206  0
         catch ( XmlPullParserException e )
 1207  
         {
 1208  0
             throw new MojoExecutionException( "Error parsing remote resource bundle descriptor.", e );
 1209  
         }
 1210  0
         catch ( Exception e )
 1211  
         {
 1212  0
             throw new MojoExecutionException( "Error rendering velocity resource.", e );
 1213  8
         }
 1214  8
     }
 1215  
 
 1216  
     protected Model getSupplement( Xpp3Dom supplementModelXml )
 1217  
         throws MojoExecutionException
 1218  
     {
 1219  0
         MavenXpp3Reader modelReader = new MavenXpp3Reader();
 1220  0
         Model model = null;
 1221  
 
 1222  
         try
 1223  
         {
 1224  0
             model = modelReader.read( new StringReader( supplementModelXml.toString() ) );
 1225  0
             String groupId = model.getGroupId();
 1226  0
             String artifactId = model.getArtifactId();
 1227  
 
 1228  0
             if ( groupId == null || groupId.trim().equals( "" ) )
 1229  
             {
 1230  0
                 throw new MojoExecutionException(
 1231  
                     "Supplemental project XML " + "requires that a <groupId> element be present." );
 1232  
             }
 1233  
 
 1234  0
             if ( artifactId == null || artifactId.trim().equals( "" ) )
 1235  
             {
 1236  0
                 throw new MojoExecutionException(
 1237  
                     "Supplemental project XML " + "requires that a <artifactId> element be present." );
 1238  
             }
 1239  
         }
 1240  0
         catch ( IOException e )
 1241  
         {
 1242  0
             getLog().warn( "Unable to read supplemental XML: " + e.getMessage(), e );
 1243  
         }
 1244  0
         catch ( XmlPullParserException e )
 1245  
         {
 1246  0
             getLog().warn( "Unable to parse supplemental XML: " + e.getMessage(), e );
 1247  0
         }
 1248  
 
 1249  0
         return model;
 1250  
     }
 1251  
 
 1252  
     protected Model mergeModels( Model parent, Model child )
 1253  
     {
 1254  0
         inheritanceAssembler.assembleModelInheritance( child, parent );
 1255  0
         return child;
 1256  
     }
 1257  
 
 1258  
     private static String generateSupplementMapKey( String groupId, String artifactId )
 1259  
     {
 1260  0
         return groupId.trim() + ":" + artifactId.trim();
 1261  
     }
 1262  
 
 1263  
     private Map<String, Model> loadSupplements( String models[] )
 1264  
         throws MojoExecutionException
 1265  
     {
 1266  8
         if ( models == null )
 1267  
         {
 1268  8
             getLog().debug( "Supplemental data models won't be loaded.  " + "No models specified." );
 1269  8
             return Collections.emptyMap();
 1270  
         }
 1271  
 
 1272  0
         List<Supplement> supplements = new ArrayList<Supplement>();
 1273  0
         for ( int idx = 0; idx < models.length; idx++ )
 1274  
         {
 1275  0
             String set = models[idx];
 1276  0
             getLog().debug( "Preparing ruleset: " + set );
 1277  
             try
 1278  
             {
 1279  0
                 File f = locator.getResourceAsFile( set, getLocationTemp( set ) );
 1280  
 
 1281  0
                 if ( null == f || !f.exists() )
 1282  
                 {
 1283  0
                     throw new MojoExecutionException( "Cold not resolve " + set );
 1284  
                 }
 1285  0
                 if ( !f.canRead() )
 1286  
                 {
 1287  0
                     throw new MojoExecutionException( "Supplemental data models won't be loaded. " + "File " +
 1288  
                         f.getAbsolutePath() + " cannot be read, check permissions on the file." );
 1289  
                 }
 1290  
 
 1291  0
                 getLog().debug( "Loading supplemental models from " + f.getAbsolutePath() );
 1292  
 
 1293  0
                 SupplementalDataModelXpp3Reader reader = new SupplementalDataModelXpp3Reader();
 1294  0
                 SupplementalDataModel supplementalModel = reader.read( new FileReader( f ) );
 1295  0
                 supplements.addAll( supplementalModel.getSupplement() );
 1296  
             }
 1297  0
             catch ( Exception e )
 1298  
             {
 1299  0
                 String msg = "Error loading supplemental data models: " + e.getMessage();
 1300  0
                 getLog().error( msg, e );
 1301  0
                 throw new MojoExecutionException( msg, e );
 1302  0
             }
 1303  
         }
 1304  
 
 1305  0
         getLog().debug( "Loading supplements complete." );
 1306  
 
 1307  0
         Map<String, Model> supplementMap = new HashMap<String, Model>();
 1308  0
         for ( Supplement sd : supplements )
 1309  
         {
 1310  0
             Xpp3Dom dom = (Xpp3Dom) sd.getProject();
 1311  
 
 1312  0
             Model m = getSupplement( dom );
 1313  0
             supplementMap.put( generateSupplementMapKey( m.getGroupId(), m.getArtifactId() ), m );
 1314  0
         }
 1315  
 
 1316  0
         return supplementMap;
 1317  
     }
 1318  
 
 1319  
     /**
 1320  
      * Convenience method to get the location of the specified file name.
 1321  
      *
 1322  
      * @param name the name of the file whose location is to be resolved
 1323  
      * @return a String that contains the absolute file name of the file
 1324  
      */
 1325  
     private String getLocationTemp( String name )
 1326  
     {
 1327  0
         String loc = name;
 1328  0
         if ( loc.indexOf( '/' ) != -1 )
 1329  
         {
 1330  0
             loc = loc.substring( loc.lastIndexOf( '/' ) + 1 );
 1331  
         }
 1332  0
         if ( loc.indexOf( '\\' ) != -1 )
 1333  
         {
 1334  0
             loc = loc.substring( loc.lastIndexOf( '\\' ) + 1 );
 1335  
         }
 1336  0
         getLog().debug( "Before: " + name + " After: " + loc );
 1337  0
         return loc;
 1338  
     }
 1339  
 
 1340  8
     class OrganizationComparator
 1341  
         implements Comparator<Organization>
 1342  
     {
 1343  
         public int compare( Organization org1, Organization org2 )
 1344  
         {
 1345  0
             int i = compareStrings( org1.getName(), org2.getName() );
 1346  0
             if (i == 0)
 1347  
             {
 1348  0
                 i = compareStrings( org1.getUrl(), org2.getUrl() );
 1349  
             }
 1350  0
             return i;
 1351  
         }
 1352  
 
 1353  
         public boolean equals( Organization o1, Organization o2 )
 1354  
         {
 1355  0
             return compare(o1, o2) == 0;
 1356  
         }
 1357  
 
 1358  
         private int compareStrings( String s1, String s2 ) {
 1359  0
             if ( s1 == null && s2 == null )
 1360  
             {
 1361  0
                 return 0;
 1362  
             }
 1363  0
             else if ( s1 == null && s2 != null )
 1364  
             {
 1365  0
                 return 1;
 1366  
             }
 1367  0
             else if ( s1 != null && s2 == null )
 1368  
             {
 1369  0
                 return -1;
 1370  
             }
 1371  
 
 1372  0
             return s1.compareToIgnoreCase( s2 );
 1373  
         }
 1374  
     }
 1375  
 
 1376  7
     class ProjectComparator
 1377  
         implements Comparator<MavenProject>
 1378  
     {
 1379  
         @SuppressWarnings( "unchecked" )
 1380  
         public int compare( MavenProject p1, MavenProject p2 )
 1381  
         {
 1382  0
             return p1.getArtifact().compareTo( p2.getArtifact() );
 1383  
         }
 1384  
 
 1385  
         public boolean equals( MavenProject p1, MavenProject p2 )
 1386  
         {
 1387  0
             return p1.getArtifact().equals( p2.getArtifact() );
 1388  
         }
 1389  
     }
 1390  
 
 1391  
 }