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