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