Coverage Report - org.apache.maven.plugins.shade.mojo.ShadeMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
ShadeMojo
0%
0/225
0%
0/116
6
 
 1  
 package org.apache.maven.plugins.shade.mojo;
 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 java.io.File;
 23  
 import java.io.FileInputStream;
 24  
 import java.io.FileOutputStream;
 25  
 import java.io.IOException;
 26  
 import java.io.Writer;
 27  
 import java.util.ArrayList;
 28  
 import java.util.Arrays;
 29  
 import java.util.Collections;
 30  
 import java.util.HashMap;
 31  
 import java.util.HashSet;
 32  
 import java.util.Iterator;
 33  
 import java.util.LinkedHashSet;
 34  
 import java.util.List;
 35  
 import java.util.Map;
 36  
 import java.util.Set;
 37  
 
 38  
 import org.apache.maven.artifact.Artifact;
 39  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 40  
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 41  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 42  
 import org.apache.maven.artifact.resolver.ArtifactCollector;
 43  
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 44  
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 45  
 import org.apache.maven.artifact.resolver.ArtifactResolver;
 46  
 import org.apache.maven.model.Dependency;
 47  
 import org.apache.maven.model.Exclusion;
 48  
 import org.apache.maven.model.Model;
 49  
 import org.apache.maven.plugin.AbstractMojo;
 50  
 import org.apache.maven.plugin.MojoExecutionException;
 51  
 import org.apache.maven.plugins.shade.Shader;
 52  
 import org.apache.maven.plugins.shade.filter.SimpleFilter;
 53  
 import org.apache.maven.plugins.shade.pom.PomWriter;
 54  
 import org.apache.maven.plugins.shade.relocation.SimpleRelocator;
 55  
 import org.apache.maven.plugins.shade.resource.ResourceTransformer;
 56  
 import org.apache.maven.project.MavenProject;
 57  
 import org.apache.maven.project.MavenProjectBuilder;
 58  
 import org.apache.maven.project.MavenProjectHelper;
 59  
 import org.apache.maven.project.ProjectBuildingException;
 60  
 import org.apache.maven.shared.dependency.tree.DependencyNode;
 61  
 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
 62  
 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
 63  
 import org.codehaus.plexus.util.FileUtils;
 64  
 import org.codehaus.plexus.util.IOUtil;
 65  
 import org.codehaus.plexus.util.WriterFactory;
 66  
 
 67  
 /**
 68  
  * Mojo that performs shading delegating to the Shader component.
 69  
  *
 70  
  * @author Jason van Zyl
 71  
  * @author Mauro Talevi
 72  
  * @author David Blevins
 73  
  * @author Hiram Chirino
 74  
  * @goal shade
 75  
  * @phase package
 76  
  * @requiresDependencyResolution runtime
 77  
  */
 78  0
 public class ShadeMojo
 79  
     extends AbstractMojo
 80  
 {
 81  
     /**
 82  
      * @parameter default-value="${project}"
 83  
      * @readonly
 84  
      * @required
 85  
      */
 86  
     private MavenProject project;
 87  
 
 88  
     /**
 89  
      * @component
 90  
      * @required
 91  
      * @readonly
 92  
      */
 93  
     private MavenProjectHelper projectHelper;
 94  
 
 95  
     /**
 96  
      * @component
 97  
      * @required
 98  
      * @readonly
 99  
      */
 100  
     private Shader shader;
 101  
 
 102  
     /**
 103  
      * The dependency tree builder to use.
 104  
      *
 105  
      * @component
 106  
      * @required
 107  
      * @readonly
 108  
      */
 109  
     private DependencyTreeBuilder dependencyTreeBuilder;
 110  
 
 111  
     /**
 112  
      * ProjectBuilder, needed to create projects from the artifacts.
 113  
      *
 114  
      * @component
 115  
      * @required
 116  
      * @readonly
 117  
      */
 118  
     private MavenProjectBuilder mavenProjectBuilder;
 119  
 
 120  
     /**
 121  
      * The artifact metadata source to use.
 122  
      *
 123  
      * @component
 124  
      * @required
 125  
      * @readonly
 126  
      */
 127  
     private ArtifactMetadataSource artifactMetadataSource;
 128  
 
 129  
     /**
 130  
      * The artifact collector to use.
 131  
      *
 132  
      * @component
 133  
      * @required
 134  
      * @readonly
 135  
      */
 136  
     private ArtifactCollector artifactCollector;
 137  
 
 138  
     /**
 139  
      * Remote repositories which will be searched for source attachments.
 140  
      *
 141  
      * @parameter default-value="${project.remoteArtifactRepositories}"
 142  
      * @required
 143  
      * @readonly
 144  
      */
 145  
     protected List remoteArtifactRepositories;
 146  
 
 147  
     /**
 148  
      * Local maven repository.
 149  
      *
 150  
      * @parameter default-value="${localRepository}"
 151  
      * @required
 152  
      * @readonly
 153  
      */
 154  
     protected ArtifactRepository localRepository;
 155  
 
 156  
     /**
 157  
      * Artifact factory, needed to download source jars for inclusion in classpath.
 158  
      *
 159  
      * @component
 160  
      * @required
 161  
      * @readonly
 162  
      */
 163  
     protected ArtifactFactory artifactFactory;
 164  
 
 165  
     /**
 166  
      * Artifact resolver, needed to download source jars for inclusion in classpath.
 167  
      *
 168  
      * @component
 169  
      * @required
 170  
      * @readonly
 171  
      */
 172  
     protected ArtifactResolver artifactResolver;
 173  
 
 174  
     /**
 175  
      * Artifacts to include/exclude from the final artifact. Artifacts are denoted by composite identifiers of the
 176  
      * general form <code>groupId:artifactId:type:classifier</code>. Since version 1.3, the wildcard characters '*' and
 177  
      * '?' can be used within the sub parts of those composite identifiers to do pattern matching. For convenience, the
 178  
      * syntax <code>groupId</code> is equivalent to <code>groupId:*:*:*</code>, <code>groupId:artifactId</code> is
 179  
      * equivalent to <code>groupId:artifactId:*:*</code> and <code>groupId:artifactId:classifier</code> is equivalent to
 180  
      * <code>groupId:artifactId:*:classifier</code>.
 181  
      * 
 182  
      * @parameter
 183  
      */
 184  
     private ArtifactSet artifactSet;
 185  
 
 186  
     /**
 187  
      * Packages to be relocated.
 188  
      *
 189  
      * @parameter
 190  
      */
 191  
     private PackageRelocation[] relocations;
 192  
 
 193  
     /**
 194  
      * Resource transformers to be used.
 195  
      *
 196  
      * @parameter
 197  
      */
 198  
     private ResourceTransformer[] transformers;
 199  
 
 200  
     /**
 201  
      * Archive Filters to be used. Allows you to specify an artifact in the form of a composite identifier as used by
 202  
      * {@link #artifactSet} and a set of include/exclude file patterns for filtering which contents of the archive are
 203  
      * added to the shaded jar. From a logical perspective, includes are processed before excludes, thus it's possible
 204  
      * to use an include to collect a set of files from the archive then use excludes to further reduce the set. By
 205  
      * default, all files are included and no files are excluded. If multiple filters apply to an artifact, the
 206  
      * intersection of the matched files will be included in the final JAR.
 207  
      * 
 208  
      * @parameter
 209  
      */
 210  
     private ArchiveFilter[] filters;
 211  
 
 212  
     /**
 213  
      * The destination directory for the shaded artifact.
 214  
      *
 215  
      * @parameter default-value="${project.build.directory}"
 216  
      */
 217  
     private File outputDirectory;
 218  
 
 219  
     /**
 220  
      * The name of the shaded artifactId.
 221  
      * 
 222  
      * If you like to change the name of the native artifact, you may use the &lt;build>&lt;finalName> setting.
 223  
      * If this is set to something different than &lt;build>&lt;finalName>, no file replacement
 224  
      * will be performed, even if shadedArtifactAttached is being used.
 225  
      *
 226  
      * @parameter expression="${finalName}"
 227  
      */
 228  
     private String finalName;
 229  
 
 230  
     /**
 231  
      * The name of the shaded artifactId. So you may want to use a different artifactId and keep
 232  
      * the standard version. If the original artifactId was "foo" then the final artifact would
 233  
      * be something like foo-1.0.jar. So if you change the artifactId you might have something
 234  
      * like foo-special-1.0.jar.
 235  
      *
 236  
      * @parameter expression="${shadedArtifactId}" default-value="${project.artifactId}"
 237  
      */
 238  
     private String shadedArtifactId;
 239  
 
 240  
     /**
 241  
      * If specified, this will include only artifacts which have groupIds which
 242  
      * start with this.
 243  
      *
 244  
      * @parameter expression="${shadedGroupFilter}"
 245  
      */
 246  
     private String shadedGroupFilter;
 247  
 
 248  
     /**
 249  
      * Defines whether the shaded artifact should be attached as classifier to
 250  
      * the original artifact.  If false, the shaded jar will be the main artifact
 251  
      * of the project
 252  
      *
 253  
      * @parameter expression="${shadedArtifactAttached}" default-value="false"
 254  
      */
 255  
     private boolean shadedArtifactAttached;
 256  
 
 257  
     /**
 258  
      * Flag whether to generate a simplified POM for the shaded artifact. If set to <code>true</code>, dependencies that
 259  
      * have been included into the uber JAR will be removed from the <code>&lt;dependencies&gt;</code> section of the
 260  
      * generated POM. The reduced POM will be named <code>dependency-reduced-pom.xml</code> and is stored into the same
 261  
      * directory as the shaded artifact.
 262  
      *
 263  
      * @parameter expression="${createDependencyReducedPom}" default-value="true"
 264  
      */
 265  
     private boolean createDependencyReducedPom;
 266  
 
 267  
     /**
 268  
      * When true, dependencies are kept in the pom but with scope 'provided'; when false,
 269  
      * the dependency is removed.
 270  
      *
 271  
      * @parameter expression="${keepDependenciesWithProvidedScope}" default-value="false"
 272  
      */
 273  
     private boolean keepDependenciesWithProvidedScope;
 274  
 
 275  
     /**
 276  
      * When true, transitive deps of removed dependencies are promoted to direct dependencies.
 277  
      * This should allow the drop in replacement of the removed deps with the new shaded
 278  
      * jar and everything should still work.
 279  
      *
 280  
      * @parameter expression="${promoteTransitiveDependencies}" default-value="false"
 281  
      */
 282  
     private boolean promoteTransitiveDependencies;
 283  
 
 284  
     /**
 285  
      * The name of the classifier used in case the shaded artifact is attached.
 286  
      *
 287  
      * @parameter expression="${shadedClassifierName}" default-value="shaded"
 288  
      */
 289  
     private String shadedClassifierName;
 290  
 
 291  
     /**
 292  
      * When true, it will attempt to create a sources jar as well
 293  
      *
 294  
      * @parameter expression="${createSourcesJar}" default-value="false"
 295  
      */
 296  
     private boolean createSourcesJar;
 297  
 
 298  
     /**
 299  
      * The path to the output file for the shaded artifact. When this parameter is set, the created archive will neither
 300  
      * replace the project's main artifact nor will it be attached. Hence, this parameter causes the parameters
 301  
      * {@link #finalName}, {@link #shadedArtifactAttached}, {@link #shadedClassifierName} and
 302  
      * {@link #createDependencyReducedPom} to be ignored when used.
 303  
      * 
 304  
      * @parameter
 305  
      * @since 1.3
 306  
      */
 307  
     private File outputFile;
 308  
 
 309  
     /** @throws MojoExecutionException  */
 310  
     public void execute()
 311  
         throws MojoExecutionException
 312  
     {
 313  0
         Set artifacts = new LinkedHashSet();
 314  0
         Set artifactIds = new LinkedHashSet();
 315  0
         Set sourceArtifacts = new LinkedHashSet();
 316  
 
 317  0
         ArtifactSelector artifactSelector =
 318  
             new ArtifactSelector( project.getArtifact(), artifactSet, shadedGroupFilter );
 319  
 
 320  0
         if ( artifactSelector.isSelected( project.getArtifact() ) && !"pom".equals( project.getArtifact().getType() ) )
 321  
         {
 322  0
             if ( project.getArtifact().getFile() == null )
 323  
             {
 324  0
                 getLog().error( "The project main artifact does not exist. This could have the following" );
 325  0
                 getLog().error( "reasons:" );
 326  0
                 getLog().error( "- You have invoked the goal directly from the command line. This is not" );
 327  0
                 getLog().error( "  supported. Please add the goal to the default lifecycle via an" );
 328  0
                 getLog().error( "  <execution> element in your POM and use \"mvn package\" to have it run." );
 329  0
                 getLog().error( "- You have bound the goal to a lifecycle phase before \"package\". Please" );
 330  0
                 getLog().error( "  remove this binding from your POM such that the goal will be run in" );
 331  0
                 getLog().error( "  the proper phase." );
 332  0
                 throw new MojoExecutionException( "Failed to create shaded artifact.",
 333  
                                                   new IllegalStateException( "Project main artifact does not exist." ) );
 334  
             }
 335  
 
 336  0
             artifacts.add( project.getArtifact().getFile() );
 337  
 
 338  0
             if ( createSourcesJar )
 339  
             {
 340  0
                 File file = shadedSourcesArtifactFile();
 341  0
                 if ( file.isFile() )
 342  
                 {
 343  0
                     sourceArtifacts.add( file );
 344  
                 }
 345  
             }
 346  
         }
 347  
 
 348  0
         for ( Iterator it = project.getArtifacts().iterator(); it.hasNext(); )
 349  
         {
 350  0
             Artifact artifact = (Artifact) it.next();
 351  
 
 352  0
             if ( !artifactSelector.isSelected( artifact ) )
 353  
             {
 354  0
                 getLog().info( "Excluding " + artifact.getId() + " from the shaded jar." );
 355  
 
 356  0
                 continue;
 357  
             }
 358  
 
 359  0
             if ( "pom".equals( artifact.getType() ) )
 360  
             {
 361  0
                 getLog().info( "Skipping pom dependency " + artifact.getId() + " in the shaded jar." );
 362  0
                 continue;
 363  
             }
 364  
 
 365  0
             getLog().info( "Including " + artifact.getId() + " in the shaded jar." );
 366  
 
 367  0
             artifacts.add( artifact.getFile() );
 368  
 
 369  0
             artifactIds.add( getId( artifact ) );
 370  
 
 371  0
             if ( createSourcesJar )
 372  
             {
 373  0
                 File file = resolveArtifactSources( artifact );
 374  0
                 if ( file != null )
 375  
                 {
 376  0
                     sourceArtifacts.add( file );
 377  
                 }
 378  
             }
 379  
         }
 380  
 
 381  
 
 382  0
         File outputJar = ( outputFile != null ) ? outputFile : shadedArtifactFileWithClassifier();
 383  0
         File sourcesJar = shadedSourceArtifactFileWithClassifier();
 384  
 
 385  
         // Now add our extra resources
 386  
         try
 387  
         {
 388  0
             List filters = getFilters();
 389  
 
 390  0
             List relocators = getRelocators();
 391  
 
 392  0
             List resourceTransformers = getResourceTransformers();
 393  
 
 394  0
             shader.shade( artifacts, outputJar, filters, relocators, resourceTransformers );
 395  
 
 396  0
             if ( createSourcesJar )
 397  
             {
 398  0
                 shader.shade( sourceArtifacts, sourcesJar, filters, relocators, resourceTransformers );
 399  
             }
 400  
 
 401  0
             if ( outputFile == null )
 402  
             {
 403  0
                 boolean renamed = false;
 404  
 
 405  
                 // rename the output file if a specific finalName is set
 406  
                 // but don't rename if the finalName is the <build><finalName>
 407  
                 // because this will be handled implicitely later
 408  0
                 if ( finalName != null && finalName.length() > 0 && !finalName.equals( project.getBuild().getFinalName() ) )
 409  
                 {
 410  0
                     String finalFileName = finalName + "." + project.getArtifact().getArtifactHandler().getExtension();
 411  0
                     File finalFile = new File( outputDirectory, finalFileName );
 412  0
                     replaceFile( finalFile, outputJar );
 413  0
                     outputJar = finalFile;
 414  
 
 415  0
                     renamed = true;
 416  
                 }
 417  
 
 418  0
                 if ( shadedArtifactAttached )
 419  
                 {
 420  0
                     getLog().info( "Attaching shaded artifact." );
 421  0
                     projectHelper.attachArtifact( project, project.getArtifact().getType(), shadedClassifierName,
 422  
                                                   outputJar );
 423  0
                     if ( createSourcesJar )
 424  
                     {
 425  0
                         projectHelper.attachArtifact( project, "jar", shadedClassifierName + "-sources", sourcesJar );
 426  
                     }
 427  
                 }
 428  0
                 else if ( !renamed )
 429  
                 {
 430  0
                     getLog().info( "Replacing original artifact with shaded artifact." );
 431  0
                     File originalArtifact = project.getArtifact().getFile();
 432  0
                     replaceFile( originalArtifact, outputJar );
 433  
 
 434  0
                     if ( createSourcesJar )
 435  
                     {
 436  0
                         File shadedSources = shadedSourcesArtifactFile();
 437  
 
 438  0
                         replaceFile( shadedSources, sourcesJar );
 439  
 
 440  0
                         projectHelper.attachArtifact( project, "jar", "sources", shadedSources );
 441  
                     }
 442  
 
 443  0
                     if ( createDependencyReducedPom )
 444  
                     {
 445  0
                         createDependencyReducedPom( artifactIds );
 446  
                     }
 447  
                 }
 448  
             }
 449  
         }
 450  0
         catch ( Exception e )
 451  
         {
 452  0
             throw new MojoExecutionException( "Error creating shaded jar: " + e.getMessage(), e );
 453  0
         }
 454  0
     }
 455  
 
 456  
     private void replaceFile( File oldFile, File newFile ) throws MojoExecutionException
 457  
     {
 458  0
         getLog().info( "Replacing " + oldFile + " with " + newFile );
 459  
 
 460  0
         File origFile = new File( outputDirectory, "original-" + oldFile.getName() );
 461  0
         if ( oldFile.exists() && !oldFile.renameTo( origFile ) )
 462  
         {
 463  
             //try a gc to see if an unclosed stream needs garbage collecting
 464  0
             System.gc();
 465  0
             System.gc();
 466  
 
 467  0
             if ( !oldFile.renameTo( origFile ) )
 468  
             {
 469  
                 // Still didn't work.   We'll do a copy
 470  
                 try
 471  
                 {
 472  0
                     FileOutputStream fout = new FileOutputStream( origFile );
 473  0
                     FileInputStream fin = new FileInputStream( oldFile );
 474  
                     try
 475  
                     {
 476  0
                         IOUtil.copy( fin, fout );
 477  
                     }
 478  
                     finally
 479  
                     {
 480  0
                         IOUtil.close( fin );
 481  0
                         IOUtil.close( fout );
 482  0
                     }
 483  
                 }
 484  0
                 catch ( IOException ex )
 485  
                 {
 486  
                     //kind of ignorable here.   We're just trying to save the original
 487  0
                     getLog().warn( ex );
 488  0
                 }
 489  
             }
 490  
         }
 491  0
         if ( !newFile.renameTo( oldFile ) )
 492  
         {
 493  
             //try a gc to see if an unclosed stream needs garbage collecting
 494  0
             System.gc();
 495  0
             System.gc();
 496  
 
 497  0
             if ( !newFile.renameTo( oldFile ) )
 498  
             {
 499  
                 // Still didn't work.   We'll do a copy
 500  
                 try
 501  
                 {
 502  0
                     FileOutputStream fout = new FileOutputStream( oldFile );
 503  0
                     FileInputStream fin = new FileInputStream( newFile );
 504  
                     try
 505  
                     {
 506  0
                         IOUtil.copy( fin, fout );
 507  
                     }
 508  
                     finally
 509  
                     {
 510  0
                         IOUtil.close( fin );
 511  0
                         IOUtil.close( fout );
 512  0
                     }
 513  
                 }
 514  0
                 catch ( IOException ex )
 515  
                 {
 516  0
                     throw new MojoExecutionException( "Could not replace original artifact with shaded artifact!", ex );
 517  0
                 }
 518  
             }
 519  
         }
 520  0
     }
 521  
 
 522  
     private File resolveArtifactSources( Artifact artifact )
 523  
     {
 524  
 
 525  0
         Artifact resolvedArtifact =
 526  
             artifactFactory.createArtifactWithClassifier( artifact.getGroupId(),
 527  
                                                           artifact.getArtifactId(),
 528  
                                                           artifact.getVersion(),
 529  
                                                           "java-source",
 530  
                                                           "sources" );
 531  
 
 532  
         try
 533  
         {
 534  0
             artifactResolver.resolve( resolvedArtifact, remoteArtifactRepositories, localRepository );
 535  
         }
 536  0
         catch ( ArtifactNotFoundException e )
 537  
         {
 538  
             // ignore, the jar has not been found
 539  
         }
 540  0
         catch ( ArtifactResolutionException e )
 541  
         {
 542  0
             getLog().warn( "Could not get sources for " + artifact );
 543  0
         }
 544  
 
 545  0
         if ( resolvedArtifact.isResolved() )
 546  
         {
 547  0
             return resolvedArtifact.getFile();
 548  
         }
 549  0
         return null;
 550  
     }
 551  
 
 552  
     private List getRelocators()
 553  
     {
 554  0
         List relocators = new ArrayList();
 555  
 
 556  0
         if ( relocations == null )
 557  
         {
 558  0
             return relocators;
 559  
         }
 560  
 
 561  0
         for ( int i = 0; i < relocations.length; i++ )
 562  
         {
 563  0
             PackageRelocation r = relocations[i];
 564  
 
 565  0
             relocators.add( new SimpleRelocator( r.getPattern(), r.getShadedPattern(), r.getExcludes() ) );
 566  
         }
 567  
 
 568  0
         return relocators;
 569  
     }
 570  
 
 571  
     private List getResourceTransformers()
 572  
     {
 573  0
         if ( transformers == null )
 574  
         {
 575  0
             return Collections.EMPTY_LIST;
 576  
         }
 577  
 
 578  0
         return Arrays.asList( transformers );
 579  
     }
 580  
 
 581  
     private List getFilters()
 582  
     {
 583  0
         List filters = new ArrayList();
 584  
 
 585  0
         if ( this.filters == null || this.filters.length <= 0 )
 586  
         {
 587  0
             return filters;
 588  
         }
 589  
 
 590  0
         Map artifacts = new HashMap();
 591  
 
 592  0
         artifacts.put( project.getArtifact(), new ArtifactId( project.getArtifact() ) );
 593  
 
 594  0
         for ( Iterator it = project.getArtifacts().iterator(); it.hasNext(); )
 595  
         {
 596  0
             Artifact artifact = (Artifact) it.next();
 597  
 
 598  0
             artifacts.put( artifact, new ArtifactId( artifact ) );
 599  
         }
 600  
 
 601  0
         for ( int i = 0; i < this.filters.length; i++ )
 602  
         {
 603  0
             ArchiveFilter filter = this.filters[i];
 604  
 
 605  0
             ArtifactId pattern = new ArtifactId( filter.getArtifact() );
 606  
 
 607  0
             Set jars = new HashSet();
 608  
 
 609  0
             for ( Iterator it = artifacts.entrySet().iterator(); it.hasNext(); )
 610  
             {
 611  0
                 Map.Entry entry = (Map.Entry) it.next();
 612  
 
 613  0
                 if ( ( (ArtifactId) entry.getValue() ).matches( pattern ) )
 614  
                 {
 615  0
                     jars.add( ( (Artifact) entry.getKey() ).getFile() );
 616  
                 }
 617  
             }
 618  
 
 619  0
             if ( jars.isEmpty() )
 620  
             {
 621  0
                 getLog().info( "No artifact matching filter " + filter.getArtifact() );
 622  
 
 623  0
                 continue;
 624  
             }
 625  
 
 626  0
             filters.add( new SimpleFilter( jars, filter.getIncludes(), filter.getExcludes() ) );
 627  
 
 628  
         }
 629  
 
 630  0
         return filters;
 631  
     }
 632  
 
 633  
     private File shadedArtifactFileWithClassifier()
 634  
     {
 635  0
         Artifact artifact = project.getArtifact();
 636  0
         final String shadedName =
 637  
             shadedArtifactId + "-" + artifact.getVersion() + "-" + shadedClassifierName + "."
 638  
                 + artifact.getArtifactHandler().getExtension();
 639  0
         return new File( outputDirectory, shadedName );
 640  
     }
 641  
 
 642  
     private File shadedSourceArtifactFileWithClassifier()
 643  
     {
 644  0
         Artifact artifact = project.getArtifact();
 645  0
         final String shadedName =
 646  
             shadedArtifactId + "-" + artifact.getVersion() + "-" + shadedClassifierName + "-sources."
 647  
                 + artifact.getArtifactHandler().getExtension();
 648  0
         return new File( outputDirectory, shadedName );
 649  
     }
 650  
 
 651  
     private File shadedSourcesArtifactFile()
 652  
     {
 653  0
         Artifact artifact = project.getArtifact();
 654  
 
 655  
         String shadedName;
 656  
 
 657  0
         if ( project.getBuild().getFinalName() != null )
 658  
         {
 659  0
             shadedName = project.getBuild().getFinalName() + "-sources." + artifact.getArtifactHandler().getExtension();
 660  
         }
 661  
         else
 662  
         {
 663  0
             shadedName = shadedArtifactId + "-" + artifact.getVersion() + "-sources."
 664  
                 + artifact.getArtifactHandler().getExtension();
 665  
         }
 666  
 
 667  0
         return new File( outputDirectory, shadedName );
 668  
     }
 669  
 
 670  
     // We need to find the direct dependencies that have been included in the uber JAR so that we can modify the
 671  
     // POM accordingly.
 672  
     private void createDependencyReducedPom( Set artifactsToRemove )
 673  
         throws IOException, DependencyTreeBuilderException, ProjectBuildingException
 674  
     {
 675  0
         Model model = project.getOriginalModel();
 676  0
         List dependencies = new ArrayList();
 677  
 
 678  0
         boolean modified = false;
 679  
 
 680  0
         List transitiveDeps = new ArrayList();
 681  
 
 682  0
         for ( Iterator it = project.getArtifacts().iterator(); it.hasNext(); )
 683  
         {
 684  0
             Artifact artifact = (Artifact) it.next();
 685  
 
 686  
             //promote
 687  0
             Dependency dep = new Dependency();
 688  0
             dep.setArtifactId( artifact.getArtifactId() );
 689  0
             if ( artifact.hasClassifier() )
 690  
             {
 691  0
                 dep.setClassifier( artifact.getClassifier() );
 692  
             }
 693  0
             dep.setGroupId( artifact.getGroupId() );
 694  0
             dep.setOptional( artifact.isOptional() );
 695  0
             dep.setScope( artifact.getScope() );
 696  0
             dep.setType( artifact.getType() );
 697  0
             dep.setVersion( artifact.getVersion() );
 698  
 
 699  
             //we'll figure out the exclusions in a bit.
 700  
 
 701  0
             transitiveDeps.add( dep );
 702  
         }
 703  0
         List origDeps = project.getDependencies();
 704  
 
 705  0
         if ( promoteTransitiveDependencies )
 706  
         {
 707  0
             origDeps = transitiveDeps;
 708  
         }
 709  
 
 710  0
         for ( Iterator i = origDeps.iterator(); i.hasNext(); )
 711  
         {
 712  0
             Dependency d = (Dependency) i.next();
 713  
 
 714  0
             dependencies.add( d );
 715  
 
 716  0
             String id = getId( d );
 717  
 
 718  0
             if ( artifactsToRemove.contains( id ) )
 719  
             {
 720  0
                 modified = true;
 721  
 
 722  0
                 if ( keepDependenciesWithProvidedScope )
 723  
                 {
 724  0
                     d.setScope( "provided" );
 725  
                 }
 726  
                 else
 727  
                 {
 728  0
                     dependencies.remove( d );
 729  
                 }
 730  
             }
 731  
         }
 732  
 
 733  
         // Check to see if we have a reduction and if so rewrite the POM.
 734  0
         if ( modified )
 735  
         {
 736  0
             while ( modified )
 737  
             {
 738  
 
 739  0
                 model.setDependencies( dependencies );
 740  
 
 741  
                 /*
 742  
                  * NOTE: Be sure to create the POM in the original base directory to be able to resolve the relativePath
 743  
                  * to local parent POMs when invoking the project builder below.
 744  
                  */
 745  0
                 File f = new File( project.getBasedir(), "dependency-reduced-pom.xml" );
 746  0
                 if ( f.exists() )
 747  
                 {
 748  0
                     f.delete();
 749  
                 }
 750  
 
 751  0
                 Writer w = WriterFactory.newXmlWriter( f );
 752  
 
 753  
                 try
 754  
                 {
 755  0
                     PomWriter.write( w, model, true );
 756  
                 }
 757  
                 finally
 758  
                 {
 759  0
                     w.close();
 760  0
                 }
 761  
 
 762  0
                 MavenProject p2 = mavenProjectBuilder.build( f, localRepository, null );
 763  0
                 modified = updateExcludesInDeps( p2, dependencies, transitiveDeps );
 764  
 
 765  
             }
 766  
 
 767  
             /*
 768  
              * NOTE: Although the dependency reduced POM in the project directory is temporary build output, we have to
 769  
              * use that for the file of the project instead of something in target to avoid messing up the base
 770  
              * directory of the project. We'll delete this file on exit to make sure it gets cleaned up but keep a copy
 771  
              * for inspection in the target directory as well.
 772  
              */
 773  0
             File f = new File( project.getBasedir(), "dependency-reduced-pom.xml" );
 774  0
             File f2 = new File( outputDirectory, "dependency-reduced-pom.xml" );
 775  0
             FileUtils.copyFile( f, f2 );
 776  0
             FileUtils.forceDeleteOnExit( f );
 777  0
             project.setFile( f );
 778  
         }
 779  0
     }
 780  
 
 781  
     private String getId( Artifact artifact )
 782  
     {
 783  0
         return getId( artifact.getGroupId(), artifact.getArtifactId(), artifact.getType(), artifact.getClassifier() );
 784  
     }
 785  
 
 786  
     private String getId( Dependency dependency )
 787  
     {
 788  0
         return getId( dependency.getGroupId(), dependency.getArtifactId(), dependency.getType(),
 789  
                       dependency.getClassifier() );
 790  
     }
 791  
 
 792  
     private String getId( String groupId, String artifactId, String type, String classifier )
 793  
     {
 794  0
         return groupId + ":" + artifactId + ":" + type + ":" + ( ( classifier != null ) ? classifier : "" );
 795  
     }
 796  
 
 797  
     public boolean updateExcludesInDeps( MavenProject project,
 798  
                                          List dependencies,
 799  
                                          List transitiveDeps )
 800  
         throws DependencyTreeBuilderException
 801  
     {
 802  0
         DependencyNode node = dependencyTreeBuilder.buildDependencyTree(
 803  
                                                   project,
 804  
                                                   localRepository,
 805  
                                                   artifactFactory,
 806  
                                                   artifactMetadataSource,
 807  
                                                   null,
 808  
                                                   artifactCollector );
 809  0
         boolean modified = false;
 810  0
         Iterator it = node.getChildren().listIterator();
 811  0
         while ( it.hasNext() )
 812  
         {
 813  0
             DependencyNode n2 = (DependencyNode) it.next();
 814  0
             Iterator it2 = n2.getChildren().listIterator();
 815  0
             while ( it2.hasNext() )
 816  
             {
 817  0
                 DependencyNode n3 = (DependencyNode) it2.next();
 818  
                 //anything two levels deep that is marked "included"
 819  
                 //is stuff that was excluded by the original poms, make sure it
 820  
                 //remains excluded IF promoting transitives.
 821  0
                 if ( n3.getState() == DependencyNode.INCLUDED )
 822  
                 {
 823  
                     //check if it really isn't in the list of original dependencies.  Maven
 824  
                     //prior to 2.0.8 may grab versions from transients instead of
 825  
                     //from the direct deps in which case they would be marked included
 826  
                     //instead of OMITTED_FOR_DUPLICATE
 827  
 
 828  
                     //also, if not promoting the transitives, level 2's would be included
 829  0
                     boolean found = false;
 830  0
                     for ( int x = 0; x < transitiveDeps.size(); x++ )
 831  
                     {
 832  0
                         Dependency dep = (Dependency) transitiveDeps.get( x );
 833  0
                         if ( dep.getArtifactId().equals( n3.getArtifact().getArtifactId() )
 834  
                             && dep.getGroupId().equals( n3.getArtifact().getGroupId() ) )
 835  
                         {
 836  0
                             found = true;
 837  
                         }
 838  
 
 839  
                     }
 840  
 
 841  0
                     if ( !found )
 842  
                     {
 843  0
                         for ( int x = 0; x < dependencies.size(); x++ )
 844  
                         {
 845  0
                             Dependency dep = (Dependency) dependencies.get( x );
 846  0
                             if ( dep.getArtifactId().equals( n2.getArtifact().getArtifactId() )
 847  
                                 && dep.getGroupId().equals( n2.getArtifact().getGroupId() ) )
 848  
                             {
 849  0
                                 Exclusion exclusion = new Exclusion();
 850  0
                                 exclusion.setArtifactId( n3.getArtifact().getArtifactId() );
 851  0
                                 exclusion.setGroupId( n3.getArtifact().getGroupId() );
 852  0
                                 dep.addExclusion( exclusion );
 853  0
                                 modified = true;
 854  0
                                 break;
 855  
                             }
 856  
                         }
 857  
                     }
 858  
                 }
 859  
             }
 860  
         }
 861  0
         return modified;
 862  
     }
 863  
 }