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