Coverage Report - org.apache.maven.plugin.source.AbstractSourceJarMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractSourceJarMojo
67%
76/113
57%
37/64
4.267
 
 1  
 package org.apache.maven.plugin.source;
 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.archiver.MavenArchiveConfiguration;
 23  
 import org.apache.maven.archiver.MavenArchiver;
 24  
 import org.apache.maven.artifact.DependencyResolutionRequiredException;
 25  
 import org.apache.maven.model.Resource;
 26  
 import org.apache.maven.plugin.AbstractMojo;
 27  
 import org.apache.maven.plugin.MojoExecutionException;
 28  
 import org.apache.maven.plugins.annotations.Component;
 29  
 import org.apache.maven.plugins.annotations.Parameter;
 30  
 import org.apache.maven.project.MavenProject;
 31  
 import org.apache.maven.project.MavenProjectHelper;
 32  
 import org.codehaus.plexus.archiver.Archiver;
 33  
 import org.codehaus.plexus.archiver.ArchiverException;
 34  
 import org.codehaus.plexus.archiver.jar.JarArchiver;
 35  
 import org.codehaus.plexus.archiver.jar.ManifestException;
 36  
 import org.codehaus.plexus.util.FileUtils;
 37  
 
 38  
 import java.io.File;
 39  
 import java.io.IOException;
 40  
 import java.util.ArrayList;
 41  
 import java.util.Arrays;
 42  
 import java.util.List;
 43  
 
 44  
 /**
 45  
  * Base class for bundling sources into a jar archive.
 46  
  *
 47  
  * @version $Id: AbstractSourceJarMojo.java 1356885 2012-07-03 19:39:07Z olamy $
 48  
  * @since 2.0.3
 49  
  */
 50  16
 public abstract class AbstractSourceJarMojo
 51  
     extends AbstractMojo
 52  
 {
 53  2
     private static final String[] DEFAULT_INCLUDES = new String[]{ "**/*" };
 54  
 
 55  2
     private static final String[] DEFAULT_EXCLUDES = new String[]{ };
 56  
 
 57  
     /**
 58  
      * List of files to include. Specified as fileset patterns which are relative to the input directory whose contents
 59  
      * is being packaged into the JAR.
 60  
      *
 61  
      * @since 2.1
 62  
      */
 63  
     @Parameter
 64  
     private String[] includes;
 65  
 
 66  
     /**
 67  
      * List of files to exclude. Specified as fileset patterns which are relative to the input directory whose contents
 68  
      * is being packaged into the JAR.
 69  
      *
 70  
      * @since 2.1
 71  
      */
 72  
     @Parameter
 73  
     private String[] excludes;
 74  
 
 75  
     /**
 76  
      * Exclude commonly excluded files such as SCM configuration. These are defined in the plexus
 77  
      * FileUtils.getDefaultExcludes()
 78  
      *
 79  
      * @since 2.1
 80  
      */
 81  
     @Parameter( defaultValue = "true" )
 82  
     private boolean useDefaultExcludes;
 83  
 
 84  
     /**
 85  
      * The Maven Project Object
 86  
      *
 87  
      */
 88  
     @Parameter(defaultValue = "${project}", readonly = true, required = true)
 89  
     protected MavenProject project;
 90  
 
 91  
     /**
 92  
      * The Jar archiver.
 93  
      */
 94  
     @Component( role = Archiver.class, hint = "jar" )
 95  
     private JarArchiver jarArchiver;
 96  
 
 97  
     /**
 98  
      * The archive configuration to use. See <a href="http://maven.apache.org/shared/maven-archiver/index.html">Maven
 99  
      * Archiver Reference</a>.
 100  
      *
 101  
      * @since 2.1
 102  
      */
 103  16
     @Parameter
 104  
     private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
 105  
 
 106  
     /**
 107  
      * Path to the default MANIFEST file to use. It will be used if <code>useDefaultManifestFile</code> is set to
 108  
      * <code>true</code>.
 109  
      *
 110  
      * @since 2.1
 111  
      */
 112  
     @Parameter( defaultValue = "${project.build.outputDirectory}/META-INF/MANIFEST.MF", readonly = false,
 113  
                 required = true )
 114  
     private File defaultManifestFile;
 115  
 
 116  
     /**
 117  
      * Set this to <code>true</code> to enable the use of the <code>defaultManifestFile</code>. <br/>
 118  
      *
 119  
      * @since 2.1
 120  
      */
 121  
     @Parameter( defaultValue = "false" )
 122  
     private boolean useDefaultManifestFile;
 123  
 
 124  
     /**
 125  
      * Specifies whether or not to attach the artifact to the project
 126  
      */
 127  
     @Parameter( property = "attach", defaultValue = "true" )
 128  
     private boolean attach;
 129  
 
 130  
     /**
 131  
      * Specifies whether or not to exclude resources from the sources-jar. This
 132  
      * can be convenient if your project includes large resources, such as
 133  
      * images, and you don't want to include them in the sources-jar.
 134  
      *
 135  
      * @since 2.0.4
 136  
      */
 137  
     @Parameter( property = "source.excludeResources", defaultValue = "false" )
 138  
     protected boolean excludeResources;
 139  
 
 140  
     /**
 141  
      * Specifies whether or not to include the POM file in the sources-jar.
 142  
      *
 143  
      * @since 2.1
 144  
      */
 145  
     @Parameter( property = "source.includePom", defaultValue = "false" )
 146  
     protected boolean includePom;
 147  
 
 148  
     /**
 149  
      * Used for attaching the source jar to the project.
 150  
      */
 151  
     @Component
 152  
     private MavenProjectHelper projectHelper;
 153  
 
 154  
     /**
 155  
      * The directory where the generated archive file will be put.
 156  
      */
 157  
     @Parameter( defaultValue = "${project.build.directory}" )
 158  
     protected File outputDirectory;
 159  
 
 160  
     /**
 161  
      * The filename to be used for the generated archive file.
 162  
      * For the source:jar goal, "-sources" is appended to this filename.
 163  
      * For the source:test-jar goal, "-test-sources" is appended.
 164  
      */
 165  
     @Parameter( defaultValue = "${project.build.finalName}" )
 166  
     protected String finalName;
 167  
 
 168  
     /**
 169  
      * Contains the full list of projects in the reactor.
 170  
      */
 171  
     @Parameter( defaultValue = "${reactorProjects}", readonly = true )
 172  
     protected List reactorProjects;
 173  
 
 174  
     /**
 175  
      * Whether creating the archive should be forced.  If set to true, the jar will
 176  
      * always be created.  If set to false, the jar will only be created when the
 177  
      * sources are newer than the jar.
 178  
      *
 179  
      * @since 2.1
 180  
      */
 181  
     @Parameter( property = "source.forceCreation", defaultValue = "false" )
 182  
     private boolean forceCreation;
 183  
 
 184  
     /**
 185  
      * A flag used to disable the source procedure. This is primarily intended for usage from the command line to
 186  
      * occasionally adjust the build.
 187  
      *
 188  
      * @since 2.2
 189  
      */
 190  
     @Parameter( property = "source.skip", defaultValue = "false" )
 191  
     private boolean skipSource;
 192  
 
 193  
     // ----------------------------------------------------------------------
 194  
     // Public methods
 195  
     // ----------------------------------------------------------------------
 196  
 
 197  
     /**
 198  
      * {@inheritDoc}
 199  
      */
 200  
     public void execute()
 201  
         throws MojoExecutionException
 202  
     {
 203  16
         if ( skipSource )
 204  
         {
 205  0
             getLog().info( "Skipping source per configuration." );
 206  0
             return;
 207  
         }
 208  
 
 209  16
         packageSources( project );
 210  16
     }
 211  
 
 212  
     // ----------------------------------------------------------------------
 213  
     // Protected methods
 214  
     // ----------------------------------------------------------------------
 215  
 
 216  
     /**
 217  
      * @return the wanted classifier, ie <code>sources</code> or <code>test-sources</code>
 218  
      */
 219  
     protected abstract String getClassifier();
 220  
 
 221  
     /**
 222  
      * @param p not null
 223  
      * @return the compile or test sources
 224  
      */
 225  
     protected abstract List<String> getSources( MavenProject p )
 226  
         throws MojoExecutionException;
 227  
 
 228  
     /**
 229  
      * @param p not null
 230  
      * @return the compile or test resources
 231  
      */
 232  
     protected abstract List<Resource> getResources( MavenProject p )
 233  
         throws MojoExecutionException;
 234  
 
 235  
     protected void packageSources( MavenProject p )
 236  
         throws MojoExecutionException
 237  
     {
 238  16
         if ( !"pom".equals( p.getPackaging() ) )
 239  
         {
 240  12
             packageSources( Arrays.asList( p ) );
 241  
         }
 242  16
     }
 243  
 
 244  
     protected void packageSources( List<MavenProject> projects )
 245  
         throws MojoExecutionException
 246  
     {
 247  12
         if ( project.getArtifact().getClassifier() != null )
 248  
         {
 249  0
             getLog().warn( "NOT adding sources to artifacts with classifier as Maven only supports one classifier "
 250  
                                + "per artifact. Current artifact [" + project.getArtifact().getId() + "] has a ["
 251  
                                + project.getArtifact().getClassifier() + "] classifier." );
 252  
 
 253  0
             return;
 254  
         }
 255  
 
 256  12
         MavenArchiver archiver = createArchiver();
 257  
 
 258  12
         for ( MavenProject project : projects )
 259  
         {
 260  12
             MavenProject subProject = getProject( project );
 261  
 
 262  12
             if ( "pom".equals( subProject.getPackaging() ) )
 263  
             {
 264  0
                 continue;
 265  
             }
 266  
 
 267  12
             archiveProjectContent( subProject, archiver.getArchiver() );
 268  12
         }
 269  
 
 270  12
         if ( !archiver.getArchiver().getFiles().isEmpty() )
 271  
         {
 272  
 
 273  12
             if ( useDefaultManifestFile && defaultManifestFile.exists() && archive.getManifestFile() == null )
 274  
             {
 275  0
                 getLog().info( "Adding existing MANIFEST to archive. Found under: " + defaultManifestFile.getPath() );
 276  0
                 archive.setManifestFile( defaultManifestFile );
 277  
             }
 278  
 
 279  12
             File outputFile = new File( outputDirectory, finalName + "-" + getClassifier() + getExtension() );
 280  
 
 281  
             try
 282  
             {
 283  12
                 archiver.setOutputFile( outputFile );
 284  
 
 285  12
                 archive.setAddMavenDescriptor( false );
 286  12
                 archive.setForced( forceCreation );
 287  
 
 288  12
                 archiver.createArchive( project, archive );
 289  
             }
 290  0
             catch ( IOException e )
 291  
             {
 292  0
                 throw new MojoExecutionException( "Error creating source archive: " + e.getMessage(), e );
 293  
             }
 294  0
             catch ( ArchiverException e )
 295  
             {
 296  0
                 throw new MojoExecutionException( "Error creating source archive: " + e.getMessage(), e );
 297  
             }
 298  0
             catch ( DependencyResolutionRequiredException e )
 299  
             {
 300  0
                 throw new MojoExecutionException( "Error creating source archive: " + e.getMessage(), e );
 301  
             }
 302  0
             catch ( ManifestException e )
 303  
             {
 304  0
                 throw new MojoExecutionException( "Error creating source archive: " + e.getMessage(), e );
 305  12
             }
 306  
 
 307  12
             if ( attach )
 308  
             {
 309  0
                 projectHelper.attachArtifact( project, getType(), getClassifier(), outputFile );
 310  
             }
 311  
             else
 312  
             {
 313  12
                 getLog().info( "NOT adding java-sources to attached artifacts list." );
 314  
             }
 315  12
         }
 316  
         else
 317  
         {
 318  0
             getLog().info( "No sources in project. Archive not created." );
 319  
         }
 320  12
     }
 321  
 
 322  
     protected void archiveProjectContent( MavenProject p, Archiver archiver )
 323  
         throws MojoExecutionException
 324  
     {
 325  12
         if ( includePom )
 326  
         {
 327  
             try
 328  
             {
 329  2
                 archiver.addFile( p.getFile(), p.getFile().getName() );
 330  
             }
 331  0
             catch ( ArchiverException e )
 332  
             {
 333  0
                 throw new MojoExecutionException( "Error adding POM file to target jar file.", e );
 334  2
             }
 335  
         }
 336  
 
 337  12
         for ( String s : getSources( p ) )
 338  
         {
 339  
 
 340  12
             File sourceDirectory = new File( s );
 341  
 
 342  12
             if ( sourceDirectory.exists() )
 343  
             {
 344  12
                 addDirectory( archiver, sourceDirectory, getCombinedIncludes( null ), getCombinedExcludes( null ) );
 345  
             }
 346  12
         }
 347  
 
 348  
         //MAPI: this should be taken from the resources plugin
 349  12
         for ( Resource resource : getResources( p ) )
 350  
         {
 351  
 
 352  12
             File sourceDirectory = new File( resource.getDirectory() );
 353  
 
 354  12
             if ( !sourceDirectory.exists() )
 355  
             {
 356  0
                 continue;
 357  
             }
 358  
 
 359  12
             List resourceIncludes = resource.getIncludes();
 360  
 
 361  12
             String[] combinedIncludes = getCombinedIncludes( resourceIncludes );
 362  
 
 363  12
             List resourceExcludes = resource.getExcludes();
 364  
 
 365  12
             String[] combinedExcludes = getCombinedExcludes( resourceExcludes );
 366  
 
 367  12
             String targetPath = resource.getTargetPath();
 368  12
             if ( targetPath != null )
 369  
             {
 370  0
                 if ( !targetPath.trim().endsWith( "/" ) )
 371  
                 {
 372  0
                     targetPath += "/";
 373  
                 }
 374  0
                 addDirectory( archiver, sourceDirectory, targetPath, combinedIncludes, combinedExcludes );
 375  
             }
 376  
             else
 377  
             {
 378  12
                 addDirectory( archiver, sourceDirectory, combinedIncludes, combinedExcludes );
 379  
             }
 380  12
         }
 381  12
     }
 382  
 
 383  
     protected MavenArchiver createArchiver()
 384  
         throws MojoExecutionException
 385  
     {
 386  12
         MavenArchiver archiver = new MavenArchiver();
 387  12
         archiver.setArchiver( jarArchiver );
 388  
 
 389  12
         if ( project.getBuild() != null )
 390  
         {
 391  12
             List<Resource> resources = project.getBuild().getResources();
 392  
 
 393  12
             for ( Resource r : resources )
 394  
             {
 395  
 
 396  0
                 if ( r.getDirectory().endsWith( "maven-shared-archive-resources" ) )
 397  
                 {
 398  0
                     addDirectory( archiver.getArchiver(), new File( r.getDirectory() ), getCombinedIncludes( null ),
 399  
                                   getCombinedExcludes( null ) );
 400  
                 }
 401  
             }
 402  
         }
 403  
 
 404  12
         return archiver;
 405  
     }
 406  
 
 407  
     protected void addDirectory( Archiver archiver, File sourceDirectory, String[] includes, String[] excludes )
 408  
         throws MojoExecutionException
 409  
     {
 410  
         try
 411  
         {
 412  24
             archiver.addDirectory( sourceDirectory, includes, excludes );
 413  
         }
 414  0
         catch ( ArchiverException e )
 415  
         {
 416  0
             throw new MojoExecutionException( "Error adding directory to source archive.", e );
 417  24
         }
 418  24
     }
 419  
 
 420  
     protected void addDirectory( Archiver archiver, File sourceDirectory, String prefix, String[] includes,
 421  
                                  String[] excludes )
 422  
         throws MojoExecutionException
 423  
     {
 424  
         try
 425  
         {
 426  0
             archiver.addDirectory( sourceDirectory, prefix, includes, excludes );
 427  
         }
 428  0
         catch ( ArchiverException e )
 429  
         {
 430  0
             throw new MojoExecutionException( "Error adding directory to source archive.", e );
 431  0
         }
 432  0
     }
 433  
 
 434  
     protected String getExtension()
 435  
     {
 436  12
         return ".jar";
 437  
     }
 438  
 
 439  
     protected MavenProject getProject( MavenProject p )
 440  
     {
 441  12
         if ( p.getExecutionProject() != null )
 442  
         {
 443  0
             return p.getExecutionProject();
 444  
         }
 445  
 
 446  12
         return p;
 447  
     }
 448  
 
 449  
     protected String getType()
 450  
     {
 451  0
         return "java-source";
 452  
     }
 453  
 
 454  
     /**
 455  
      * Combines the includes parameter and additional includes. Defaults to {@link #DEFAULT_INCLUDES} If the
 456  
      * additionalIncludes parameter is null, it is not added to the combined includes.
 457  
      *
 458  
      * @param additionalIncludes The includes specified in the pom resources section
 459  
      * @return The combined array of includes.
 460  
      */
 461  
     private String[] getCombinedIncludes( List additionalIncludes )
 462  
     {
 463  24
         List<String> combinedIncludes = new ArrayList<String>();
 464  
 
 465  24
         if ( includes != null && includes.length > 0 )
 466  
         {
 467  0
             combinedIncludes.addAll( Arrays.asList( includes ) );
 468  
         }
 469  
 
 470  24
         if ( additionalIncludes != null && additionalIncludes.size() > 0 )
 471  
         {
 472  2
             combinedIncludes.addAll( additionalIncludes );
 473  
         }
 474  
 
 475  
         // If there are no other includes, use the default.
 476  24
         if ( combinedIncludes.size() == 0 )
 477  
         {
 478  22
             combinedIncludes.addAll( Arrays.asList( DEFAULT_INCLUDES ) );
 479  
         }
 480  
 
 481  24
         return combinedIncludes.toArray( new String[combinedIncludes.size()] );
 482  
     }
 483  
 
 484  
     /**
 485  
      * Combines the user parameter {@link #excludes}, the default excludes from plexus FileUtils,
 486  
      * and the contents of the parameter addionalExcludes.
 487  
      *
 488  
      * @param additionalExcludes Additional excludes to add to the array
 489  
      * @return The combined list of excludes.
 490  
      */
 491  
 
 492  
     private String[] getCombinedExcludes( List additionalExcludes )
 493  
     {
 494  24
         List<String> combinedExcludes = new ArrayList<String>();
 495  
 
 496  24
         if ( useDefaultExcludes )
 497  
         {
 498  0
             combinedExcludes.addAll( FileUtils.getDefaultExcludesAsList() );
 499  
         }
 500  
 
 501  24
         if ( excludes != null && excludes.length > 0 )
 502  
         {
 503  0
             combinedExcludes.addAll( Arrays.asList( excludes ) );
 504  
         }
 505  
 
 506  24
         if ( additionalExcludes != null && additionalExcludes.size() > 0 )
 507  
         {
 508  4
             combinedExcludes.addAll( additionalExcludes );
 509  
         }
 510  
 
 511  24
         if ( combinedExcludes.size() == 0 )
 512  
         {
 513  20
             combinedExcludes.addAll( Arrays.asList( DEFAULT_EXCLUDES ) );
 514  
         }
 515  
 
 516  24
         return combinedExcludes.toArray( new String[combinedExcludes.size()] );
 517  
     }
 518  
 }