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