Coverage Report - org.apache.maven.plugin.ear.EarMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
EarMojo
0%
0/139
0%
0/78
4.214
 
 1  
 package org.apache.maven.plugin.ear;
 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.execution.MavenSession;
 25  
 import org.apache.maven.plugin.MojoExecutionException;
 26  
 import org.apache.maven.plugin.MojoFailureException;
 27  
 import org.apache.maven.plugin.ear.util.EarMavenArchiver;
 28  
 import org.apache.maven.plugin.ear.util.JavaEEVersion;
 29  
 import org.apache.maven.project.MavenProjectHelper;
 30  
 import org.apache.maven.shared.filtering.MavenFileFilter;
 31  
 import org.apache.maven.shared.filtering.MavenFilteringException;
 32  
 import org.apache.maven.shared.filtering.MavenResourcesExecution;
 33  
 import org.apache.maven.shared.filtering.MavenResourcesFiltering;
 34  
 import org.codehaus.plexus.archiver.ArchiverException;
 35  
 import org.codehaus.plexus.archiver.UnArchiver;
 36  
 import org.codehaus.plexus.archiver.jar.JarArchiver;
 37  
 import org.codehaus.plexus.archiver.manager.ArchiverManager;
 38  
 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
 39  
 import org.codehaus.plexus.util.DirectoryScanner;
 40  
 import org.codehaus.plexus.util.FileUtils;
 41  
 import org.codehaus.plexus.util.StringUtils;
 42  
 
 43  
 import java.io.File;
 44  
 import java.io.IOException;
 45  
 import java.util.ArrayList;
 46  
 import java.util.Arrays;
 47  
 import java.util.Iterator;
 48  
 import java.util.List;
 49  
 
 50  
 /**
 51  
  * Builds J2EE Enterprise Archive (EAR) files.
 52  
  *
 53  
  * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
 54  
  * @version $Id: EarMojo.java 1102967 2011-05-14 07:43:24Z snicoll $
 55  
  * @goal ear
 56  
  * @phase package
 57  
  * @threadSafe
 58  
  * @requiresDependencyResolution test
 59  
  */
 60  0
 public class EarMojo
 61  
     extends AbstractEarMojo
 62  
 {
 63  0
     private static final String[] EMPTY_STRING_ARRAY = { };
 64  
 
 65  
 
 66  
     /**
 67  
      * Single directory for extra files to include in the EAR.
 68  
      *
 69  
      * @parameter default-value="${basedir}/src/main/application"
 70  
      * @required
 71  
      */
 72  
     private File earSourceDirectory;
 73  
 
 74  
     /**
 75  
      * The comma separated list of tokens to include in the EAR.
 76  
      *
 77  
      * @parameter alias="includes" default-value="**"
 78  
      */
 79  
     private String earSourceIncludes;
 80  
 
 81  
     /**
 82  
      * The comma separated list of tokens to exclude from the EAR.
 83  
      *
 84  
      * @parameter alias="excludes"
 85  
      */
 86  
     private String earSourceExcludes;
 87  
 
 88  
     /**
 89  
      * Specify that the ear sources should be filtered.
 90  
      *
 91  
      * @parameter default-value="false"
 92  
      * @since 2.3.2
 93  
      */
 94  
     private boolean filtering;
 95  
 
 96  
     /**
 97  
      * Filters (property files) to include during the interpolation of the pom.xml.
 98  
      *
 99  
      * @parameter
 100  
      * @since 2.3.2
 101  
      */
 102  
     private List filters;
 103  
 
 104  
     /**
 105  
      * A list of file extensions that should not be filtered if
 106  
      * filtering is enabled.
 107  
      *
 108  
      * @parameter
 109  
      * @since 2.3.2
 110  
      */
 111  
     private List nonFilteredFileExtensions;
 112  
 
 113  
     /**
 114  
      * To escape interpolated value with windows path
 115  
      * c:\foo\bar will be replaced with c:\\foo\\bar
 116  
      *
 117  
      * @parameter expression="${maven.ear.escapedBackslashesInFilePath}" default-value="false"
 118  
      * @since 2.3.2
 119  
      */
 120  
     private boolean escapedBackslashesInFilePath;
 121  
 
 122  
     /**
 123  
      * Expression preceded with the String won't be interpolated
 124  
      * \${foo} will be replaced with ${foo}
 125  
      *
 126  
      * @parameter expression="${maven.ear.escapeString}"
 127  
      * @since 2.3.2
 128  
      */
 129  
     protected String escapeString;
 130  
 
 131  
     /**
 132  
      * The location of the manifest file to be used within the ear file. If
 133  
      * not value if specified, the default location in the workDirectory is
 134  
      * taken. If the file does not exist, a manifest will be generated
 135  
      * automatically.
 136  
      *
 137  
      * @parameter
 138  
      */
 139  
     private File manifestFile;
 140  
 
 141  
     /**
 142  
      * The location of a custom application.xml file to be used
 143  
      * within the ear file.
 144  
      *
 145  
      * @parameter
 146  
      */
 147  
     private String applicationXml;
 148  
 
 149  
     /**
 150  
      * The directory for the generated EAR.
 151  
      *
 152  
      * @parameter default-value="${project.build.directory}"
 153  
      * @required
 154  
      */
 155  
     private String outputDirectory;
 156  
 
 157  
     /**
 158  
      * The name of the EAR file to generate.
 159  
      *
 160  
      * @parameter alias="earName" default-value="${project.build.finalName}"
 161  
      * @required
 162  
      */
 163  
     private String finalName;
 164  
 
 165  
     /**
 166  
      * The comma separated list of artifact's type(s) to unpack
 167  
      * by default.
 168  
      *
 169  
      * @parameter
 170  
      */
 171  
     private String unpackTypes;
 172  
 
 173  
     /**
 174  
      * Classifier to add to the artifact generated. If given, the artifact will
 175  
      * be an attachment instead.
 176  
      *
 177  
      * @parameter
 178  
      */
 179  
     private String classifier;
 180  
 
 181  
     /**
 182  
      * The directory to get the resources from.
 183  
      *
 184  
      * @parameter
 185  
      * @deprecated please use earSourceDirectory instead
 186  
      */
 187  
     private File resourcesDir;
 188  
 
 189  
     /**
 190  
      * The Jar archiver.
 191  
      *
 192  
      * @component role="org.codehaus.plexus.archiver.Archiver" role-hint="jar"
 193  
      */
 194  
     private JarArchiver jarArchiver;
 195  
 
 196  
     /**
 197  
      * The archive configuration to use.
 198  
      * See <a href="http://maven.apache.org/shared/maven-archiver/index.html">Maven Archiver Reference</a>.
 199  
      *
 200  
      * @parameter
 201  
      */
 202  0
     private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
 203  
 
 204  
     /**
 205  
      * @component
 206  
      */
 207  
     private MavenProjectHelper projectHelper;
 208  
 
 209  
     /**
 210  
      * The archive manager.
 211  
      *
 212  
      * @component
 213  
      */
 214  
     private ArchiverManager archiverManager;
 215  
 
 216  
     /**
 217  
      * @component role="org.apache.maven.shared.filtering.MavenFileFilter" role-hint="default"
 218  
      * @required
 219  
      */
 220  
     private MavenFileFilter mavenFileFilter;
 221  
 
 222  
     /**
 223  
      * @component role="org.apache.maven.shared.filtering.MavenResourcesFiltering" role-hint="default"
 224  
      * @required
 225  
      */
 226  
     private MavenResourcesFiltering mavenResourcesFiltering;
 227  
 
 228  
     /**
 229  
      * @parameter expression="${session}"
 230  
      * @readonly
 231  
      * @required
 232  
      * @since 2.3.2
 233  
      */
 234  
     private MavenSession session;
 235  
 
 236  
 
 237  
     private List filterWrappers;
 238  
 
 239  
 
 240  
     public void execute()
 241  
         throws MojoExecutionException, MojoFailureException
 242  
     {
 243  
         // Initializes ear modules
 244  0
         super.execute();
 245  
 
 246  0
         final JavaEEVersion javaEEVersion = JavaEEVersion.getJavaEEVersion( version );
 247  
 
 248  
         // Initializes unpack types
 249  0
         List unpackTypesList = new ArrayList();
 250  0
         if ( unpackTypes != null )
 251  
         {
 252  0
             unpackTypesList = Arrays.asList( unpackTypes.split( "," ) );
 253  0
             final Iterator it = unpackTypesList.iterator();
 254  0
             while ( it.hasNext() )
 255  
             {
 256  0
                 String type = (String) it.next();
 257  0
                 if ( !EarModuleFactory.standardArtifactTypes.contains( type ) )
 258  
                 {
 259  0
                     throw new MojoExecutionException(
 260  
                         "Invalid type[" + type + "] supported types are " + EarModuleFactory.standardArtifactTypes );
 261  
                 }
 262  0
             }
 263  0
             getLog().debug( "Initialized unpack types " + unpackTypesList );
 264  
         }
 265  
 
 266  
         // Copy modules
 267  
         try
 268  
         {
 269  0
             for ( Iterator iter = getModules().iterator(); iter.hasNext(); )
 270  
             {
 271  0
                 EarModule module = (EarModule) iter.next();
 272  0
                 if ( module instanceof JavaModule )
 273  
                 {
 274  0
                     getLog().warn( "JavaModule is deprecated (" + module + "), please use JarModule instead." );
 275  
                 }
 276  0
                 if ( module instanceof Ejb3Module )
 277  
                 {
 278  0
                     getLog().warn( "Ejb3Module is deprecated (" + module + "), please use EjbModule instead." );
 279  
                 }
 280  0
                 final File sourceFile = module.getArtifact().getFile();
 281  0
                 final File destinationFile = buildDestinationFile( getWorkDirectory(), module.getUri() );
 282  0
                 if ( !sourceFile.isFile() )
 283  
                 {
 284  0
                     throw new MojoExecutionException(
 285  
                         "Cannot copy a directory: " + sourceFile.getAbsolutePath() + "; Did you package/install " +
 286  
                             module.getArtifact() + "?" );
 287  
                 }
 288  
 
 289  0
                 if ( destinationFile.getCanonicalPath().equals( sourceFile.getCanonicalPath() ) )
 290  
                 {
 291  0
                     getLog().info(
 292  
                         "Skipping artifact[" + module + "], as it already exists at[" + module.getUri() + "]" );
 293  0
                     continue;
 294  
                 }
 295  
 
 296  
                 // If the module is within the unpack list, make sure that no unpack wasn't forced (null or true)
 297  
                 // If the module is not in the unpack list, it should be true
 298  0
                 if ( ( unpackTypesList.contains( module.getType() ) &&
 299  
                     ( module.shouldUnpack() == null || module.shouldUnpack().booleanValue() ) ) ||
 300  
                     ( module.shouldUnpack() != null && module.shouldUnpack().booleanValue() ) )
 301  
                 {
 302  0
                     getLog().info( "Copying artifact[" + module + "] to[" + module.getUri() + "] (unpacked)" );
 303  
                     // Make sure that the destination is a directory to avoid plexus nasty stuff :)
 304  0
                     destinationFile.mkdirs();
 305  0
                     unpack( sourceFile, destinationFile );
 306  
                 }
 307  
                 else
 308  
                 {
 309  0
                     if ( sourceFile.lastModified() > destinationFile.lastModified() )
 310  
                     {
 311  0
                         getLog().info( "Copying artifact[" + module + "] to[" + module.getUri() + "]" );
 312  0
                         FileUtils.copyFile( sourceFile, destinationFile );
 313  
                     }
 314  
                     else
 315  
                     {
 316  0
                         getLog().debug(
 317  
                             "Skipping artifact[" + module + "], as it is already up to date at[" + module.getUri() +
 318  
                                 "]" );
 319  
                     }
 320  
                 }
 321  0
             }
 322  
         }
 323  0
         catch ( IOException e )
 324  
         {
 325  0
             throw new MojoExecutionException( "Error copying EAR modules", e );
 326  
         }
 327  0
         catch ( ArchiverException e )
 328  
         {
 329  0
             throw new MojoExecutionException( "Error unpacking EAR modules", e );
 330  
         }
 331  0
         catch ( NoSuchArchiverException e )
 332  
         {
 333  0
             throw new MojoExecutionException( "No Archiver found for EAR modules", e );
 334  0
         }
 335  
 
 336  
         // Copy source files
 337  
         try
 338  
         {
 339  0
             File earSourceDir = earSourceDirectory;
 340  0
             if ( earSourceDir.exists() )
 341  
             {
 342  0
                 getLog().info( "Copy ear sources to " + getWorkDirectory().getAbsolutePath() );
 343  0
                 String[] fileNames = getEarFiles( earSourceDir );
 344  0
                 for ( int i = 0; i < fileNames.length; i++ )
 345  
                 {
 346  0
                     copyFile( new File( earSourceDir, fileNames[i] ), new File( getWorkDirectory(), fileNames[i] ) );
 347  
                 }
 348  
             }
 349  
 
 350  0
             if ( applicationXml != null && !"".equals( applicationXml ) )
 351  
             {
 352  
                 //rename to application.xml
 353  0
                 getLog().info( "Including custom application.xml[" + applicationXml + "]" );
 354  0
                 File metaInfDir = new File( getWorkDirectory(), META_INF );
 355  0
                 copyFile( new File( applicationXml ), new File( metaInfDir, "/application.xml" ) );
 356  
             }
 357  
 
 358  
         }
 359  0
         catch ( IOException e )
 360  
         {
 361  0
             throw new MojoExecutionException( "Error copying EAR sources", e );
 362  
         }
 363  0
         catch ( MavenFilteringException e )
 364  
         {
 365  0
             throw new MojoExecutionException( "Error filtering EAR sources", e );
 366  0
         }
 367  
 
 368  
         // Copy resources files
 369  
         try
 370  
         {
 371  0
             if ( resourcesDir != null && resourcesDir.exists() )
 372  
             {
 373  0
                 getLog().warn( "resourcesDir is deprecated. Please use the earSourceDirectory property instead." );
 374  0
                 getLog().info( "Copy ear resources to " + getWorkDirectory().getAbsolutePath() );
 375  0
                 String[] fileNames = getEarFiles( resourcesDir );
 376  0
                 for ( int i = 0; i < fileNames.length; i++ )
 377  
                 {
 378  0
                     FileUtils.copyFile( new File( resourcesDir, fileNames[i] ),
 379  
                                         new File( getWorkDirectory(), fileNames[i] ) );
 380  
                 }
 381  
             }
 382  
         }
 383  0
         catch ( IOException e )
 384  
         {
 385  0
             throw new MojoExecutionException( "Error copying EAR resources", e );
 386  0
         }
 387  
 
 388  
         // Check if deployment descriptor is there
 389  0
         File ddFile = new File( getWorkDirectory(), APPLICATION_XML_URI );
 390  0
         if ( !ddFile.exists() && ( javaEEVersion.lt( JavaEEVersion.Five ) ) )
 391  
         {
 392  0
             throw new MojoExecutionException(
 393  
                 "Deployment descriptor: " + ddFile.getAbsolutePath() + " does not exist." );
 394  
         }
 395  
 
 396  
         try
 397  
         {
 398  0
             File earFile = getEarFile( outputDirectory, finalName, classifier );
 399  0
             final MavenArchiver archiver = new EarMavenArchiver( getModules() );
 400  0
             final JarArchiver jarArchiver = getJarArchiver();
 401  0
             getLog().debug( "Jar archiver implementation[" + jarArchiver.getClass().getName() + "]" );
 402  0
             archiver.setArchiver( jarArchiver );
 403  0
             archiver.setOutputFile( earFile );
 404  
 
 405  
             // Include custom manifest if necessary
 406  0
             includeCustomManifestFile();
 407  
 
 408  0
             archiver.getArchiver().addDirectory( getWorkDirectory() );
 409  0
             archiver.createArchive( getProject(), archive );
 410  
 
 411  0
             if ( classifier != null )
 412  
             {
 413  0
                 projectHelper.attachArtifact( getProject(), "ear", classifier, earFile );
 414  
             }
 415  
             else
 416  
             {
 417  0
                 getProject().getArtifact().setFile( earFile );
 418  
             }
 419  
         }
 420  0
         catch ( Exception e )
 421  
         {
 422  0
             throw new MojoExecutionException( "Error assembling EAR", e );
 423  0
         }
 424  0
     }
 425  
 
 426  
     public String getApplicationXml()
 427  
     {
 428  0
         return applicationXml;
 429  
     }
 430  
 
 431  
     public void setApplicationXml( String applicationXml )
 432  
     {
 433  0
         this.applicationXml = applicationXml;
 434  0
     }
 435  
 
 436  
     /**
 437  
      * Returns a string array of the excludes to be used
 438  
      * when assembling/copying the ear.
 439  
      *
 440  
      * @return an array of tokens to exclude
 441  
      */
 442  
     protected String[] getExcludes()
 443  
     {
 444  0
         List excludeList = new ArrayList( FileUtils.getDefaultExcludesAsList() );
 445  0
         if ( earSourceExcludes != null && !"".equals( earSourceExcludes ) )
 446  
         {
 447  0
             excludeList.addAll( Arrays.asList( StringUtils.split( earSourceExcludes, "," ) ) );
 448  
         }
 449  
 
 450  
         // if applicationXml is specified, omit the one in the source directory
 451  0
         if ( getApplicationXml() != null && !"".equals( getApplicationXml() ) )
 452  
         {
 453  0
             excludeList.add( "**/" + META_INF + "/application.xml" );
 454  
         }
 455  
 
 456  0
         return (String[]) excludeList.toArray( EMPTY_STRING_ARRAY );
 457  
     }
 458  
 
 459  
     /**
 460  
      * Returns a string array of the includes to be used
 461  
      * when assembling/copying the ear.
 462  
      *
 463  
      * @return an array of tokens to include
 464  
      */
 465  
     protected String[] getIncludes()
 466  
     {
 467  0
         return StringUtils.split( StringUtils.defaultString( earSourceIncludes ), "," );
 468  
     }
 469  
 
 470  
     private static File buildDestinationFile( File buildDir, String uri )
 471  
     {
 472  0
         return new File( buildDir, uri );
 473  
     }
 474  
 
 475  
     private void includeCustomManifestFile()
 476  
     {
 477  0
         if ( manifestFile == null )
 478  
         {
 479  0
             manifestFile = new File( getWorkDirectory(), "META-INF/MANIFEST.MF" );
 480  
         }
 481  
 
 482  0
         if ( !manifestFile.exists() )
 483  
         {
 484  0
             getLog().info( "Could not find manifest file: " + manifestFile + " - Generating one" );
 485  
         }
 486  
         else
 487  
         {
 488  0
             getLog().info( "Including custom manifest file[" + manifestFile + "]" );
 489  0
             archive.setManifestFile( manifestFile );
 490  
         }
 491  0
     }
 492  
 
 493  
     /**
 494  
      * Returns the EAR file to generate, based on an optional classifier.
 495  
      *
 496  
      * @param basedir    the output directory
 497  
      * @param finalName  the name of the ear file
 498  
      * @param classifier an optional classifier
 499  
      * @return the EAR file to generate
 500  
      */
 501  
     private static File getEarFile( String basedir, String finalName, String classifier )
 502  
     {
 503  0
         if ( classifier == null )
 504  
         {
 505  0
             classifier = "";
 506  
         }
 507  0
         else if ( classifier.trim().length() > 0 && !classifier.startsWith( "-" ) )
 508  
         {
 509  0
             classifier = "-" + classifier;
 510  
         }
 511  
 
 512  0
         return new File( basedir, finalName + classifier + ".ear" );
 513  
     }
 514  
 
 515  
     /**
 516  
      * Returns a list of filenames that should be copied
 517  
      * over to the destination directory.
 518  
      *
 519  
      * @param sourceDir the directory to be scanned
 520  
      * @return the array of filenames, relative to the sourceDir
 521  
      */
 522  
     private String[] getEarFiles( File sourceDir )
 523  
     {
 524  0
         DirectoryScanner scanner = new DirectoryScanner();
 525  0
         scanner.setBasedir( sourceDir );
 526  0
         scanner.setExcludes( getExcludes() );
 527  0
         scanner.addDefaultExcludes();
 528  
 
 529  0
         scanner.setIncludes( getIncludes() );
 530  
 
 531  0
         scanner.scan();
 532  
 
 533  0
         return scanner.getIncludedFiles();
 534  
     }
 535  
 
 536  
     /**
 537  
      * Unpacks the module into the EAR structure.
 538  
      *
 539  
      * @param source  File to be unpacked.
 540  
      * @param destDir Location where to put the unpacked files.
 541  
      */
 542  
     public void unpack( File source, File destDir )
 543  
         throws NoSuchArchiverException, IOException, ArchiverException
 544  
     {
 545  0
         UnArchiver unArchiver = archiverManager.getUnArchiver( "zip" );
 546  0
         unArchiver.setSourceFile( source );
 547  0
         unArchiver.setDestDirectory( destDir );
 548  
 
 549  
         // Extract the module
 550  0
         unArchiver.extract();
 551  0
     }
 552  
 
 553  
     /**
 554  
      * Returns the {@link JarArchiver} implementation used
 555  
      * to package the EAR file.
 556  
      * <p/>
 557  
      * By default the archiver is obtained from the Plexus container.
 558  
      *
 559  
      * @return the archiver
 560  
      */
 561  
     protected JarArchiver getJarArchiver()
 562  
     {
 563  0
         return jarArchiver;
 564  
     }
 565  
 
 566  
     private void copyFile( File source, File target )
 567  
         throws MavenFilteringException, IOException, MojoExecutionException
 568  
     {
 569  0
         if ( filtering && !isNonFilteredExtension( source.getName() ) )
 570  
         {
 571  
             // Silly that we have to do this ourselves
 572  0
             if ( target.getParentFile() != null && !target.getParentFile().exists() )
 573  
             {
 574  0
                 target.getParentFile().mkdirs();
 575  
             }
 576  0
             mavenFileFilter.copyFile( source, target, true, getFilterWrappers(), null );
 577  
         }
 578  
         else
 579  
         {
 580  0
             FileUtils.copyFile( source, target );
 581  
         }
 582  0
     }
 583  
 
 584  
     public boolean isNonFilteredExtension( String fileName )
 585  
     {
 586  0
         return !mavenResourcesFiltering.filteredFileExtension( fileName, nonFilteredFileExtensions );
 587  
     }
 588  
 
 589  
     private List getFilterWrappers()
 590  
         throws MojoExecutionException
 591  
     {
 592  0
         if ( filterWrappers == null )
 593  
         {
 594  
             try
 595  
             {
 596  0
                 MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
 597  0
                 mavenResourcesExecution.setEscapeString( escapeString );
 598  0
                 filterWrappers =
 599  
                     mavenFileFilter.getDefaultFilterWrappers( project, filters, escapedBackslashesInFilePath,
 600  
                                                               this.session, mavenResourcesExecution );
 601  
             }
 602  0
             catch ( MavenFilteringException e )
 603  
             {
 604  0
                 getLog().error( "fail to build filering wrappers " + e.getMessage() );
 605  0
                 throw new MojoExecutionException( e.getMessage(), e );
 606  0
             }
 607  
         }
 608  0
         return filterWrappers;
 609  
     }
 610  
 }