Coverage Report - org.apache.maven.plugin.assembly.archive.task.AddDependencySetsTask
 
Classes in this File Line Coverage Branch Coverage Complexity
AddDependencySetsTask
50%
93/185
40%
33/82
3,579
 
 1  
 package org.apache.maven.plugin.assembly.archive.task;
 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.artifact.Artifact;
 23  
 import org.apache.maven.model.Dependency;
 24  
 import org.apache.maven.model.Model;
 25  
 import org.apache.maven.plugin.assembly.AssemblerConfigurationSource;
 26  
 import org.apache.maven.plugin.assembly.InvalidAssemblerConfigurationException;
 27  
 import org.apache.maven.plugin.assembly.archive.ArchiveCreationException;
 28  
 import org.apache.maven.plugin.assembly.format.AssemblyFormattingException;
 29  
 import org.apache.maven.plugin.assembly.model.DependencySet;
 30  
 import org.apache.maven.plugin.assembly.model.FileSet;
 31  
 import org.apache.maven.plugin.assembly.model.UnpackOptions;
 32  
 import org.apache.maven.plugin.assembly.utils.AssemblyFormatUtils;
 33  
 import org.apache.maven.plugin.assembly.utils.FilterUtils;
 34  
 import org.apache.maven.plugin.assembly.utils.TypeConversionUtils;
 35  
 import org.apache.maven.project.MavenProject;
 36  
 import org.apache.maven.project.MavenProjectBuilder;
 37  
 import org.apache.maven.project.ProjectBuildingException;
 38  
 import org.apache.maven.shared.artifact.filter.ScopeArtifactFilter;
 39  
 import org.codehaus.plexus.archiver.Archiver;
 40  
 import org.codehaus.plexus.archiver.ArchiverException;
 41  
 import org.codehaus.plexus.archiver.UnArchiver;
 42  
 import org.codehaus.plexus.archiver.manager.ArchiverManager;
 43  
 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
 44  
 import org.codehaus.plexus.logging.Logger;
 45  
 
 46  
 import java.io.File;
 47  
 import java.util.ArrayList;
 48  
 import java.util.Collections;
 49  
 import java.util.Iterator;
 50  
 import java.util.LinkedHashSet;
 51  
 import java.util.List;
 52  
 import java.util.Set;
 53  
 
 54  
 /**
 55  
  * @version $Id: AddDependencySetsTask.java 1402042 2012-10-25 09:36:42Z dennisl $
 56  
  */
 57  
 public class AddDependencySetsTask
 58  
     implements ArchiverTask
 59  
 {
 60  
 
 61  
     private static final List<String> NON_ARCHIVE_DEPENDENCY_TYPES;
 62  
 
 63  
     static
 64  
     {
 65  3
         final List<String> nonArch = new ArrayList<String>();
 66  
 
 67  3
         nonArch.add( "pom" );
 68  
 
 69  3
         NON_ARCHIVE_DEPENDENCY_TYPES = Collections.unmodifiableList( nonArch );
 70  3
     }
 71  
 
 72  
     private final List<DependencySet> dependencySets;
 73  
 
 74  
     private final Logger logger;
 75  
 
 76  
     private final MavenProject project;
 77  
 
 78  
     private MavenProject moduleProject;
 79  
 
 80  
     private final MavenProjectBuilder projectBuilder;
 81  
 
 82  
     private String defaultOutputDirectory;
 83  
 
 84  
     private String defaultOutputFileNameMapping;
 85  
 
 86  
     private Artifact moduleArtifact;
 87  
 
 88  
     private final Set<Artifact> resolvedArtifacts;
 89  
 
 90  
     private final ArchiverManager archiverManager;
 91  
 
 92  
     public AddDependencySetsTask( final List<DependencySet> dependencySets, final Set<Artifact> resolvedArtifacts,
 93  
                                   final MavenProject project, final MavenProjectBuilder projectBuilder,
 94  
                                   final ArchiverManager archiverManager, final Logger logger )
 95  45
     {
 96  45
         this.dependencySets = dependencySets;
 97  45
         this.resolvedArtifacts = resolvedArtifacts;
 98  45
         this.project = project;
 99  45
         this.projectBuilder = projectBuilder;
 100  45
         this.archiverManager = archiverManager;
 101  45
         this.logger = logger;
 102  45
     }
 103  
 
 104  
     public void execute( final Archiver archiver, final AssemblerConfigurationSource configSource )
 105  
         throws ArchiveCreationException, AssemblyFormattingException, InvalidAssemblerConfigurationException
 106  
     {
 107  21
         if ( ( dependencySets == null ) || dependencySets.isEmpty() )
 108  
         {
 109  12
             logger.debug( "No dependency sets specified." );
 110  12
             return;
 111  
         }
 112  
 
 113  
         @SuppressWarnings( "unchecked" )
 114  9
         final List<Dependency> deps = project.getDependencies();
 115  9
         if ( ( deps == null ) || deps.isEmpty() )
 116  
         {
 117  9
             logger.debug( "Project " + project.getId() + " has no dependencies. Skipping dependency set addition." );
 118  
         }
 119  
 
 120  9
         for ( final Iterator<DependencySet> i = dependencySets.iterator(); i.hasNext(); )
 121  
         {
 122  9
             final DependencySet dependencySet = i.next();
 123  
 
 124  9
             addDependencySet( dependencySet, archiver, configSource );
 125  9
         }
 126  9
     }
 127  
 
 128  
     protected void addDependencySet( final DependencySet dependencySet, final Archiver archiver,
 129  
                                      final AssemblerConfigurationSource configSource )
 130  
         throws AssemblyFormattingException, ArchiveCreationException, InvalidAssemblerConfigurationException
 131  
     {
 132  24
         logger.debug( "Processing DependencySet (output=" + dependencySet.getOutputDirectory() + ")" );
 133  
 
 134  24
         if ( !dependencySet.isUseTransitiveDependencies() && dependencySet.isUseTransitiveFiltering() )
 135  
         {
 136  0
             logger.warn( "DependencySet has nonsensical configuration: useTransitiveDependencies == false "
 137  
                             + "AND useTransitiveFiltering == true. Transitive filtering flag will be ignored." );
 138  
         }
 139  
 
 140  24
         final Set<Artifact> dependencyArtifacts = resolveDependencyArtifacts( dependencySet );
 141  
 
 142  24
         boolean filterContents = false;
 143  24
         final UnpackOptions opts = dependencySet.getUnpackOptions();
 144  24
         if ( dependencySet.isUnpack() && opts != null && ( opts.isFiltered() || opts.getLineEnding() != null ) )
 145  
         {
 146  0
             filterContents = true;
 147  
         }
 148  24
         else if ( dependencyArtifacts.size() > 1 )
 149  
         {
 150  0
             checkMultiArtifactOutputConfig( dependencySet );
 151  
         }
 152  
 
 153  24
         logger.debug( "Adding " + dependencyArtifacts.size() + " dependency artifacts." );
 154  
 
 155  24
         for ( final Iterator<Artifact> j = dependencyArtifacts.iterator(); j.hasNext(); )
 156  
         {
 157  21
             final Artifact depArtifact = j.next();
 158  
 
 159  
             MavenProject depProject;
 160  
             try
 161  
             {
 162  21
                 depProject =
 163  
                     projectBuilder.buildFromRepository( depArtifact, configSource.getRemoteRepositories(),
 164  
                                                         configSource.getLocalRepository() );
 165  
             }
 166  3
             catch ( final ProjectBuildingException e )
 167  
             {
 168  3
                 logger.debug( "Error retrieving POM of module-dependency: " + depArtifact.getId() + "; Reason: "
 169  
                                 + e.getMessage() + "\n\nBuilding stub project instance." );
 170  
 
 171  3
                 depProject = buildProjectStub( depArtifact );
 172  18
             }
 173  
 
 174  21
             if ( NON_ARCHIVE_DEPENDENCY_TYPES.contains( depArtifact.getType() ) )
 175  
             {
 176  0
                 addNonArchiveDependency( depArtifact, depProject, dependencySet, archiver, configSource );
 177  
             }
 178  
             else
 179  
             {
 180  21
                 if ( filterContents )
 181  
                 {
 182  0
                     addFilteredUnpackedArtifact( dependencySet, depArtifact, depProject, archiver, configSource );
 183  
                 }
 184  
                 else
 185  
                 {
 186  21
                     addNormalArtifact( dependencySet, depArtifact, depProject, archiver, configSource );
 187  
                 }
 188  
             }
 189  21
         }
 190  24
     }
 191  
 
 192  
     private void checkMultiArtifactOutputConfig( final DependencySet dependencySet )
 193  
     {
 194  0
         String dir = dependencySet.getOutputDirectory();
 195  0
         if ( dir == null )
 196  
         {
 197  0
             dir = defaultOutputDirectory;
 198  
         }
 199  
 
 200  0
         String mapping = dependencySet.getOutputFileNameMapping();
 201  0
         if ( mapping == null )
 202  
         {
 203  0
             mapping = defaultOutputFileNameMapping;
 204  
         }
 205  
 
 206  0
         if ( ( dir == null || dir.indexOf( "${" ) < 0 ) && ( mapping == null || mapping.indexOf( "${" ) < 0 ) )
 207  
         {
 208  0
             logger.warn( "NOTE: Your assembly specifies a dependencySet that matches multiple artifacts, but specifies a concrete output format. "
 209  
                             + "THIS MAY RESULT IN ONE OR MORE ARTIFACTS BEING OBSCURED!\n\nOutput directory: '"
 210  
                             + dir
 211  
                             + "'\nOutput filename mapping: '" + mapping + "'" );
 212  
         }
 213  0
     }
 214  
 
 215  
     private void addFilteredUnpackedArtifact( final DependencySet dependencySet, final Artifact depArtifact,
 216  
                                               final MavenProject depProject, final Archiver archiver,
 217  
                                               final AssemblerConfigurationSource configSource )
 218  
         throws ArchiveCreationException, AssemblyFormattingException
 219  
     {
 220  0
         logger.debug( "Adding dependency artifact " + depArtifact.getId() + " after filtering the unpacked contents." );
 221  
 
 222  0
         final StringBuilder sb =
 223  
             new StringBuilder().append( depArtifact.getGroupId() )
 224  
                                .append( "_" )
 225  
                                .append( depArtifact.getArtifactId() )
 226  
                                .append( "_" )
 227  
                                .append( depArtifact.getVersion() );
 228  
 
 229  0
         final String classifier = depArtifact.getClassifier();
 230  0
         if ( classifier != null )
 231  
         {
 232  0
             sb.append( "_" ).append( classifier );
 233  
         }
 234  
 
 235  0
         sb.append( "." ).append( depArtifact.getType() );
 236  
 
 237  0
         final File dir = new File( configSource.getWorkingDirectory(), sb.toString() );
 238  0
         if ( dir.exists() )
 239  
         {
 240  0
             logger.debug( "NOT unpacking: " + depArtifact.getId() + ". Directory already exists in workdir:\n\t"
 241  
                             + dir.getAbsolutePath() );
 242  
         }
 243  
         else
 244  
         {
 245  0
             dir.mkdirs();
 246  
 
 247  
             UnArchiver unarchiver;
 248  
             try
 249  
             {
 250  0
                 unarchiver = archiverManager.getUnArchiver( depArtifact.getFile() );
 251  
             }
 252  0
             catch ( final NoSuchArchiverException e )
 253  
             {
 254  0
                 throw new ArchiveCreationException( "Failed to retrieve un-archiver for: " + depArtifact.getId()
 255  
                                 + ". Dependency filtering cannot proceed.", e );
 256  0
             }
 257  
 
 258  0
             unarchiver.setDestDirectory( dir );
 259  0
             unarchiver.setOverwrite( true );
 260  0
             unarchiver.setSourceFile( depArtifact.getFile() );
 261  0
             unarchiver.setIgnorePermissions( configSource.isIgnorePermissions() );
 262  
 
 263  
             try
 264  
             {
 265  0
                 unarchiver.extract();
 266  
             }
 267  0
             catch ( final ArchiverException e )
 268  
             {
 269  0
                 throw new ArchiveCreationException( "Failed to unpack dependency archive: " + depArtifact.getId()
 270  
                                 + ". Dependency filtering cannot proceed.", e );
 271  0
             }
 272  
         }
 273  
 
 274  0
         final UnpackOptions opts = dependencySet.getUnpackOptions();
 275  
 
 276  0
         final FileSet fs = new FileSet();
 277  0
         fs.setDirectory( dir.getAbsolutePath() );
 278  0
         fs.setDirectoryMode( dependencySet.getDirectoryMode() );
 279  0
         fs.setExcludes( opts.getExcludes() );
 280  0
         fs.setFileMode( dependencySet.getFileMode() );
 281  0
         fs.setFiltered( opts.isFiltered() );
 282  0
         fs.setIncludes( opts.getIncludes() );
 283  
 
 284  0
         String outDir = dependencySet.getOutputDirectory();
 285  0
         if ( outDir == null )
 286  
         {
 287  0
             outDir = defaultOutputDirectory;
 288  
         }
 289  
 
 290  0
         String filenameMapping = dependencySet.getOutputFileNameMapping();
 291  0
         if ( filenameMapping == null )
 292  
         {
 293  0
             filenameMapping = defaultOutputFileNameMapping;
 294  
         }
 295  
 
 296  0
         filenameMapping =
 297  
             AssemblyFormatUtils.evaluateFileNameMapping( filenameMapping, depArtifact, configSource.getProject(),
 298  
                                                          moduleProject, moduleArtifact, depProject, configSource );
 299  
 
 300  0
         final String outputLocation = new File( outDir, filenameMapping ).getPath();
 301  
 
 302  0
         fs.setOutputDirectory( outputLocation );
 303  
 
 304  0
         fs.setLineEnding( opts.getLineEnding() );
 305  0
         fs.setUseDefaultExcludes( opts.isUseDefaultExcludes() );
 306  
 
 307  0
         final AddFileSetsTask task = new AddFileSetsTask( fs );
 308  0
         task.setProject( depProject );
 309  0
         task.setModuleProject( moduleProject );
 310  0
         task.setLogger( logger );
 311  
 
 312  0
         task.execute( archiver, configSource );
 313  0
     }
 314  
 
 315  
     private void addNormalArtifact( final DependencySet dependencySet, final Artifact depArtifact,
 316  
                                     final MavenProject depProject, final Archiver archiver,
 317  
                                     final AssemblerConfigurationSource configSource )
 318  
         throws AssemblyFormattingException, ArchiveCreationException
 319  
     {
 320  21
         logger.debug( "Adding dependency artifact " + depArtifact.getId() + "." );
 321  
 
 322  21
         final AddArtifactTask task = new AddArtifactTask( depArtifact, logger );
 323  
 
 324  21
         task.setProject( depProject );
 325  21
         task.setModuleProject( moduleProject );
 326  21
         task.setModuleArtifact( moduleArtifact );
 327  21
         task.setOutputDirectory( dependencySet.getOutputDirectory(), defaultOutputDirectory );
 328  21
         task.setFileNameMapping( dependencySet.getOutputFileNameMapping(), defaultOutputFileNameMapping );
 329  
 
 330  21
         final int dirMode = TypeConversionUtils.modeToInt( dependencySet.getDirectoryMode(), logger );
 331  21
         if ( dirMode != -1 )
 332  
         {
 333  9
             task.setDirectoryMode( dirMode );
 334  
         }
 335  
 
 336  21
         final int fileMode = TypeConversionUtils.modeToInt( dependencySet.getFileMode(), logger );
 337  21
         if ( fileMode != -1 )
 338  
         {
 339  18
             task.setFileMode( fileMode );
 340  
         }
 341  
 
 342  21
         task.setUnpack( dependencySet.isUnpack() );
 343  
 
 344  21
         final UnpackOptions opts = dependencySet.getUnpackOptions();
 345  21
         if ( dependencySet.isUnpack() && ( opts != null ) )
 346  
         {
 347  0
             task.setIncludes( opts.getIncludes() );
 348  0
             task.setExcludes( opts.getExcludes() );
 349  
         }
 350  
 
 351  21
         task.execute( archiver, configSource );
 352  21
     }
 353  
 
 354  
     private MavenProject buildProjectStub( final Artifact depArtifact )
 355  
     {
 356  3
         final Model model = new Model();
 357  3
         model.setGroupId( depArtifact.getGroupId() );
 358  3
         model.setArtifactId( depArtifact.getArtifactId() );
 359  3
         model.setVersion( depArtifact.getBaseVersion() );
 360  3
         model.setPackaging( depArtifact.getType() );
 361  
 
 362  3
         model.setDescription( "Stub for " + depArtifact.getId() );
 363  
 
 364  3
         final MavenProject project = new MavenProject( model );
 365  3
         project.setArtifact( depArtifact );
 366  
 
 367  3
         return project;
 368  
     }
 369  
 
 370  
     protected Set<Artifact> resolveDependencyArtifacts( final DependencySet dependencySet )
 371  
         throws InvalidAssemblerConfigurationException
 372  
     {
 373  33
         final Set<Artifact> dependencyArtifacts = new LinkedHashSet<Artifact>();
 374  33
         if ( resolvedArtifacts != null )
 375  
         {
 376  30
             dependencyArtifacts.addAll( resolvedArtifacts );
 377  
         }
 378  
 
 379  33
         if ( dependencySet.isUseProjectArtifact() )
 380  
         {
 381  24
             final Artifact projectArtifact = project.getArtifact();
 382  24
             if ( ( projectArtifact != null ) && ( projectArtifact.getFile() != null ) )
 383  
             {
 384  3
                 dependencyArtifacts.add( projectArtifact );
 385  
             }
 386  
             else
 387  
             {
 388  21
                 logger.warn( "Cannot include project artifact: " + projectArtifact
 389  
                                 + "; it doesn't have an associated file or directory." );
 390  
             }
 391  
         }
 392  
 
 393  33
         if ( dependencySet.isUseProjectAttachments() )
 394  
         {
 395  
             @SuppressWarnings( "unchecked" )
 396  0
             final List<Artifact> attachments = project.getAttachedArtifacts();
 397  0
             if ( attachments != null )
 398  
             {
 399  0
                 for ( final Iterator<Artifact> attachmentIt = attachments.iterator(); attachmentIt.hasNext(); )
 400  
                 {
 401  0
                     final Artifact attachment = attachmentIt.next();
 402  
 
 403  0
                     if ( attachment.getFile() != null )
 404  
                     {
 405  0
                         dependencyArtifacts.add( attachment );
 406  
                     }
 407  
                     else
 408  
                     {
 409  0
                         logger.warn( "Cannot include attached artifact: " + project.getId() + " for project: "
 410  
                                         + project.getId() + "; it doesn't have an associated file or directory." );
 411  
                     }
 412  0
                 }
 413  
             }
 414  
         }
 415  
 
 416  33
         if ( dependencySet.isUseTransitiveFiltering() )
 417  
         {
 418  3
             logger.debug( "Filtering dependency artifacts USING transitive dependency path information." );
 419  
         }
 420  
         else
 421  
         {
 422  30
             logger.debug( "Filtering dependency artifacts WITHOUT transitive dependency path information." );
 423  
         }
 424  
 
 425  33
         final ScopeArtifactFilter filter = new ScopeArtifactFilter( dependencySet.getScope() );
 426  
 
 427  33
         FilterUtils.filterArtifacts( dependencyArtifacts, dependencySet.getIncludes(), dependencySet.getExcludes(),
 428  
                                      dependencySet.isUseStrictFiltering(), dependencySet.isUseTransitiveFiltering(),
 429  
                                      logger, filter );
 430  
 
 431  33
         return dependencyArtifacts;
 432  
     }
 433  
 
 434  
     protected void addNonArchiveDependency( final Artifact depArtifact, final MavenProject depProject,
 435  
                                             final DependencySet dependencySet, final Archiver archiver,
 436  
                                             final AssemblerConfigurationSource configSource )
 437  
         throws AssemblyFormattingException, ArchiveCreationException
 438  
     {
 439  0
         final File source = depArtifact.getFile();
 440  
 
 441  0
         String outputDirectory = dependencySet.getOutputDirectory();
 442  
 
 443  0
         outputDirectory =
 444  
             AssemblyFormatUtils.getOutputDirectory( outputDirectory, configSource.getProject(), moduleProject,
 445  
                                                     depProject, depProject.getBuild().getFinalName(), configSource );
 446  
 
 447  0
         final String destName =
 448  
             AssemblyFormatUtils.evaluateFileNameMapping( dependencySet.getOutputFileNameMapping(), depArtifact,
 449  
                                                          configSource.getProject(), moduleProject, moduleArtifact,
 450  
                                                          depProject, configSource );
 451  
 
 452  
         String target;
 453  
 
 454  
         // omit the last char if ends with / or \\
 455  0
         if ( outputDirectory.endsWith( "/" ) || outputDirectory.endsWith( "\\" ) )
 456  
         {
 457  0
             target = outputDirectory + destName;
 458  
         }
 459  
         else
 460  
         {
 461  0
             target = outputDirectory + "/" + destName;
 462  
         }
 463  
 
 464  
         try
 465  
         {
 466  0
             final int mode = TypeConversionUtils.modeToInt( dependencySet.getFileMode(), logger );
 467  0
             if ( mode > -1 )
 468  
             {
 469  0
                 archiver.addFile( source, target, mode );
 470  
             }
 471  
             else
 472  
             {
 473  0
                 archiver.addFile( source, target );
 474  
             }
 475  
         }
 476  0
         catch ( final ArchiverException e )
 477  
         {
 478  0
             throw new ArchiveCreationException( "Error adding file to archive: " + e.getMessage(), e );
 479  0
         }
 480  0
     }
 481  
 
 482  
     public List<DependencySet> getDependencySets()
 483  
     {
 484  0
         return dependencySets;
 485  
     }
 486  
 
 487  
     public Logger getLogger()
 488  
     {
 489  0
         return logger;
 490  
     }
 491  
 
 492  
     public String getDefaultOutputDirectory()
 493  
     {
 494  0
         return defaultOutputDirectory;
 495  
     }
 496  
 
 497  
     public void setDefaultOutputDirectory( final String defaultOutputDirectory )
 498  
     {
 499  15
         this.defaultOutputDirectory = defaultOutputDirectory;
 500  15
     }
 501  
 
 502  
     public String getDefaultOutputFileNameMapping()
 503  
     {
 504  0
         return defaultOutputFileNameMapping;
 505  
     }
 506  
 
 507  
     public void setDefaultOutputFileNameMapping( final String defaultOutputFileNameMapping )
 508  
     {
 509  15
         this.defaultOutputFileNameMapping = defaultOutputFileNameMapping;
 510  15
     }
 511  
 
 512  
     public MavenProject getModuleProject()
 513  
     {
 514  0
         return moduleProject;
 515  
     }
 516  
 
 517  
     public void setModuleProject( final MavenProject moduleProject )
 518  
     {
 519  15
         this.moduleProject = moduleProject;
 520  15
     }
 521  
 
 522  
     public void setModuleArtifact( final Artifact moduleArtifact )
 523  
     {
 524  15
         this.moduleArtifact = moduleArtifact;
 525  15
     }
 526  
 
 527  
     public Artifact getModuleArtifact()
 528  
     {
 529  0
         return moduleArtifact;
 530  
     }
 531  
 }