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