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