View Javadoc

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.plugins.annotations.Component;
30  import org.apache.maven.plugins.annotations.LifecyclePhase;
31  import org.apache.maven.plugins.annotations.Mojo;
32  import org.apache.maven.plugins.annotations.Parameter;
33  import org.apache.maven.plugins.annotations.ResolutionScope;
34  import org.apache.maven.project.MavenProjectHelper;
35  import org.apache.maven.shared.filtering.MavenFileFilter;
36  import org.apache.maven.shared.filtering.MavenFilteringException;
37  import org.apache.maven.shared.filtering.MavenResourcesExecution;
38  import org.apache.maven.shared.filtering.MavenResourcesFiltering;
39  import org.codehaus.plexus.archiver.Archiver;
40  import org.codehaus.plexus.archiver.ArchiverException;
41  import org.codehaus.plexus.archiver.UnArchiver;
42  import org.codehaus.plexus.archiver.jar.JarArchiver;
43  import org.codehaus.plexus.archiver.jar.Manifest;
44  import org.codehaus.plexus.archiver.jar.Manifest.Attribute;
45  import org.codehaus.plexus.archiver.jar.ManifestException;
46  import org.codehaus.plexus.archiver.manager.ArchiverManager;
47  import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
48  import org.codehaus.plexus.archiver.zip.ZipArchiver;
49  import org.codehaus.plexus.archiver.zip.ZipUnArchiver;
50  import org.codehaus.plexus.util.DirectoryScanner;
51  import org.codehaus.plexus.util.FileUtils;
52  import org.codehaus.plexus.util.StringUtils;
53  
54  import java.io.File;
55  import java.io.FileReader;
56  import java.io.IOException;
57  import java.io.PrintWriter;
58  import java.util.ArrayList;
59  import java.util.Arrays;
60  import java.util.List;
61  import java.util.zip.ZipException;
62  
63  /**
64   * Builds J2EE Enterprise Archive (EAR) files.
65   *
66   * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
67   * @version $Id: EarMojo.java 1359710 2012-07-10 14:53:53Z tchemit $
68   */
69  @Mojo( name = "ear", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true,
70         requiresDependencyResolution = ResolutionScope.TEST )
71  public class EarMojo
72      extends AbstractEarMojo
73  {
74      private static final String[] EMPTY_STRING_ARRAY = { };
75  
76  
77      /**
78       * Single directory for extra files to include in the EAR.
79       */
80      @Parameter( defaultValue = "${basedir}/src/main/application", required = true )
81      private File earSourceDirectory;
82  
83      /**
84       * The comma separated list of tokens to include in the EAR.
85       */
86      @Parameter( alias = "includes", defaultValue = "**" )
87      private String earSourceIncludes;
88  
89      /**
90       * The comma separated list of tokens to exclude from the EAR.
91       */
92      @Parameter( alias = "excludes" )
93      private String earSourceExcludes;
94  
95      /**
96       * Specify that the EAR sources should be filtered.
97       *
98       * @since 2.3.2
99       */
100     @Parameter( defaultValue = "false" )
101     private boolean filtering;
102 
103     /**
104      * Filters (property files) to include during the interpolation of the pom.xml.
105      *
106      * @since 2.3.2
107      */
108     @Parameter
109     private List filters;
110 
111     /**
112      * A list of file extensions that should not be filtered if
113      * filtering is enabled.
114      *
115      * @since 2.3.2
116      */
117     @Parameter
118     private List nonFilteredFileExtensions;
119 
120     /**
121      * To escape interpolated value with Windows path
122      * c:\foo\bar will be replaced with c:\\foo\\bar.
123      *
124      * @since 2.3.2
125      */
126     @Parameter( property = "maven.ear.escapedBackslashesInFilePath", defaultValue = "false" )
127     private boolean escapedBackslashesInFilePath;
128 
129     /**
130      * Expression preceded with this String won't be interpolated
131      * \${foo} will be replaced with ${foo}.
132      *
133      * @since 2.3.2
134      */
135     @Parameter( property = "maven.ear.escapeString" )
136     protected String escapeString;
137 
138     /**
139      * The location of the manifest file to be used within the EAR file. If
140      * no value if specified, the default location in the workDirectory is
141      * taken. If the file does not exist, a manifest will be generated
142      * automatically.
143      */
144     @Parameter
145     private File manifestFile;
146 
147     /**
148      * The location of a custom application.xml file to be used
149      * within the EAR file.
150      */
151     @Parameter
152     private String applicationXml;
153 
154     /**
155      * The directory for the generated EAR.
156      */
157     @Parameter( defaultValue = "${project.build.directory}", required = true )
158     private String outputDirectory;
159 
160     /**
161      * The name of the EAR file to generate.
162      */
163     @Parameter( alias = "earName", defaultValue = "${project.build.finalName}", required = true )
164     private String finalName;
165 
166     /**
167      * The comma separated list of artifact's type(s) to unpack
168      * by default.
169      */
170     @Parameter
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     private String classifier;
179 
180     /**
181      * A comma separated list of tokens to exclude when packaging the EAR.
182      * By default nothing is excluded. Note that you can use the Java Regular
183      * Expressions engine to include and exclude specific pattern using the
184      * expression %regex[].
185      * Hint: read the about (?!Pattern).
186      *
187      * @since 2.7
188      */
189     @Parameter
190     private String packagingExcludes;
191 
192     /**
193      * A comma separated list of tokens to include when packaging the EAR.
194      * By default everything is included. Note that you can use the Java Regular
195      * Expressions engine to include and exclude specific pattern using the
196      * expression %regex[].
197      *
198      * @since 2.7
199      */
200     @Parameter
201     private String packagingIncludes;
202 
203     /**
204      * Whether to create skinny WARs or not. A skinny WAR is a WAR that does not
205      * have all of its dependencies in WEB-INF/lib. Instead those dependencies
206      * are shared between the WARs through the EAR.
207      *
208      * @since 2.7
209      */
210     @Parameter( property = "maven.ear.skinnyWars", defaultValue = "false" )
211     private boolean skinnyWars;
212 
213     /**
214      * The Jar archiver.
215      */
216     @Component( role = Archiver.class, hint = "jar" )
217     private JarArchiver jarArchiver;
218 
219     /**
220      * The Zip archiver.
221      */
222     @Component( role = Archiver.class, hint = "zip" )
223     private ZipArchiver zipArchiver;
224 
225     /**
226      * The Zip Un archiver.
227      */
228     @Component( role = UnArchiver.class, hint = "zip" )
229     private ZipUnArchiver zipUnArchiver;
230 
231     /**
232      * The archive configuration to use.
233      * See <a href="http://maven.apache.org/shared/maven-archiver/index.html">Maven Archiver Reference</a>.
234      */
235     @Parameter
236     private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
237 
238     /**
239      */
240     @Component
241     private MavenProjectHelper projectHelper;
242 
243     /**
244      * The archive manager.
245      */
246     @Component
247     private ArchiverManager archiverManager;
248 
249     /**
250      */
251     @Component( role = MavenFileFilter.class, hint = "default" )
252     private MavenFileFilter mavenFileFilter;
253 
254     /**
255      */
256     @Component( role = MavenResourcesFiltering.class, hint = "default" )
257     private MavenResourcesFiltering mavenResourcesFiltering;
258 
259     /**
260      * @since 2.3.2
261      */
262     @Component
263     private MavenSession session;
264 
265 
266     private List filterWrappers;
267 
268 
269     public void execute()
270         throws MojoExecutionException, MojoFailureException
271     {
272         // Initializes ear modules
273         super.execute();
274 
275         final JavaEEVersion javaEEVersion = JavaEEVersion.getJavaEEVersion( version );
276 
277         // Initializes unpack types
278         List<String> unpackTypesList = new ArrayList<String>();
279         if ( unpackTypes != null )
280         {
281             unpackTypesList = Arrays.asList( unpackTypes.split( "," ) );
282             for ( String type : unpackTypesList )
283             {
284                 if ( !EarModuleFactory.standardArtifactTypes.contains( type ) )
285                 {
286                     throw new MojoExecutionException(
287                         "Invalid type [" + type + "] supported types are " + EarModuleFactory.standardArtifactTypes );
288                 }
289             }
290             getLog().debug( "Initialized unpack types " + unpackTypesList );
291         }
292 
293         // Copy modules
294         try
295         {
296             for ( EarModule module : getModules() )
297             {
298                 if ( module instanceof JavaModule )
299                 {
300                     getLog().warn( "JavaModule is deprecated (" + module + "), please use JarModule instead." );
301                 }
302                 if ( module instanceof Ejb3Module )
303                 {
304                     getLog().warn( "Ejb3Module is deprecated (" + module + "), please use EjbModule instead." );
305                 }
306                 final File sourceFile = module.getArtifact().getFile();
307                 final File destinationFile = buildDestinationFile( getWorkDirectory(), module.getUri() );
308                 if ( !sourceFile.isFile() )
309                 {
310                     throw new MojoExecutionException(
311                         "Cannot copy a directory: " + sourceFile.getAbsolutePath() + "; Did you package/install " +
312                             module.getArtifact() + "?" );
313                 }
314 
315                 if ( destinationFile.getCanonicalPath().equals( sourceFile.getCanonicalPath() ) )
316                 {
317                     getLog().info(
318                         "Skipping artifact [" + module + "], as it already exists at [" + module.getUri() + "]" );
319                     continue;
320                 }
321 
322                 // If the module is within the unpack list, make sure that no unpack wasn't forced (null or true)
323                 // If the module is not in the unpack list, it should be true
324                 if ( ( unpackTypesList.contains( module.getType() ) &&
325                     ( module.shouldUnpack() == null || module.shouldUnpack().booleanValue() ) ) ||
326                     ( module.shouldUnpack() != null && module.shouldUnpack().booleanValue() ) )
327                 {
328                     getLog().info( "Copying artifact [" + module + "] to [" + module.getUri() + "] (unpacked)" );
329                     // Make sure that the destination is a directory to avoid plexus nasty stuff :)
330                     destinationFile.mkdirs();
331                     unpack( sourceFile, destinationFile );
332 
333                     if ( skinnyWars && module.changeManifestClasspath() )
334                     {
335                         changeManifestClasspath( module, destinationFile );
336                     }
337                 }
338                 else
339                 {
340                     if ( sourceFile.lastModified() > destinationFile.lastModified() )
341                     {
342                         getLog().info( "Copying artifact [" + module + "] to [" + module.getUri() + "]" );
343                         FileUtils.copyFile( sourceFile, destinationFile );
344 
345                         if ( skinnyWars && module.changeManifestClasspath() )
346                         {
347                             changeManifestClasspath( module, destinationFile );
348                         }
349                     }
350                     else
351                     {
352                         getLog().debug(
353                             "Skipping artifact [" + module + "], as it is already up to date at [" + module.getUri() +
354                                 "]" );
355                     }
356                 }
357             }
358         }
359         catch ( IOException e )
360         {
361             throw new MojoExecutionException( "Error copying EAR modules", e );
362         }
363         catch ( ArchiverException e )
364         {
365             throw new MojoExecutionException( "Error unpacking EAR modules", e );
366         }
367         catch ( NoSuchArchiverException e )
368         {
369             throw new MojoExecutionException( "No Archiver found for EAR modules", e );
370         }
371 
372         // Copy source files
373         try
374         {
375             File earSourceDir = earSourceDirectory;
376             if ( earSourceDir.exists() )
377             {
378                 getLog().info( "Copy ear sources to " + getWorkDirectory().getAbsolutePath() );
379                 String[] fileNames = getEarFiles( earSourceDir );
380                 for ( int i = 0; i < fileNames.length; i++ )
381                 {
382                     copyFile( new File( earSourceDir, fileNames[i] ), new File( getWorkDirectory(), fileNames[i] ) );
383                 }
384             }
385 
386             if ( applicationXml != null && !"".equals( applicationXml ) )
387             {
388                 //rename to application.xml
389                 getLog().info( "Including custom application.xml[" + applicationXml + "]" );
390                 File metaInfDir = new File( getWorkDirectory(), META_INF );
391                 copyFile( new File( applicationXml ), new File( metaInfDir, "/application.xml" ) );
392             }
393 
394         }
395         catch ( IOException e )
396         {
397             throw new MojoExecutionException( "Error copying EAR sources", e );
398         }
399         catch ( MavenFilteringException e )
400         {
401             throw new MojoExecutionException( "Error filtering EAR sources", e );
402         }
403 
404         // Check if deployment descriptor is there
405         File ddFile = new File( getWorkDirectory(), APPLICATION_XML_URI );
406         if ( !ddFile.exists() && ( javaEEVersion.lt( JavaEEVersion.Five ) ) )
407         {
408             throw new MojoExecutionException(
409                 "Deployment descriptor: " + ddFile.getAbsolutePath() + " does not exist." );
410         }
411 
412         try
413         {
414             File earFile = getEarFile( outputDirectory, finalName, classifier );
415             final MavenArchiver archiver = new EarMavenArchiver( getModules() );
416             final JarArchiver jarArchiver = getJarArchiver();
417             getLog().debug( "Jar archiver implementation [" + jarArchiver.getClass().getName() + "]" );
418             archiver.setArchiver( jarArchiver );
419             archiver.setOutputFile( earFile );
420 
421             // Include custom manifest if necessary
422             includeCustomManifestFile();
423 
424             getLog().debug( "Excluding " + Arrays.asList( getPackagingExcludes() ) + " from the generated EAR." );
425             getLog().debug( "Including " + Arrays.asList( getPackagingIncludes() ) + " in the generated EAR." );
426 
427             archiver.getArchiver().addDirectory( getWorkDirectory(), getPackagingIncludes(), getPackagingExcludes() );
428             archiver.createArchive( session, getProject(), archive );
429 
430             if ( classifier != null )
431             {
432                 projectHelper.attachArtifact( getProject(), "ear", classifier, earFile );
433             }
434             else
435             {
436                 getProject().getArtifact().setFile( earFile );
437             }
438         }
439         catch ( Exception e )
440         {
441             throw new MojoExecutionException( "Error assembling EAR", e );
442         }
443     }
444 
445     public String getApplicationXml()
446     {
447         return applicationXml;
448     }
449 
450     public void setApplicationXml( String applicationXml )
451     {
452         this.applicationXml = applicationXml;
453     }
454 
455     /**
456      * Returns a string array of the excludes to be used
457      * when assembling/copying the ear.
458      *
459      * @return an array of tokens to exclude
460      */
461     protected String[] getExcludes()
462     {
463         @SuppressWarnings( "unchecked" ) List<String> excludeList =
464             new ArrayList<String>( FileUtils.getDefaultExcludesAsList() );
465         if ( earSourceExcludes != null && !"".equals( earSourceExcludes ) )
466         {
467             excludeList.addAll( Arrays.asList( StringUtils.split( earSourceExcludes, "," ) ) );
468         }
469 
470         // if applicationXml is specified, omit the one in the source directory
471         if ( getApplicationXml() != null && !"".equals( getApplicationXml() ) )
472         {
473             excludeList.add( "**/" + META_INF + "/application.xml" );
474         }
475 
476         return (String[]) excludeList.toArray( EMPTY_STRING_ARRAY );
477     }
478 
479     /**
480      * Returns a string array of the includes to be used
481      * when assembling/copying the ear.
482      *
483      * @return an array of tokens to include
484      */
485     protected String[] getIncludes()
486     {
487         return StringUtils.split( StringUtils.defaultString( earSourceIncludes ), "," );
488     }
489 
490     public String[] getPackagingExcludes()
491     {
492         if ( StringUtils.isEmpty( packagingExcludes ) )
493         {
494             return new String[0];
495         }
496         else
497         {
498             return StringUtils.split( packagingExcludes, "," );
499         }
500     }
501 
502     public void setPackagingExcludes( String packagingExcludes )
503     {
504         this.packagingExcludes = packagingExcludes;
505     }
506 
507     public String[] getPackagingIncludes()
508     {
509         if ( StringUtils.isEmpty( packagingIncludes ) )
510         {
511             return new String[]{ "**" };
512         }
513         else
514         {
515             return StringUtils.split( packagingIncludes, "," );
516         }
517     }
518 
519     public void setPackagingIncludes( String packagingIncludes )
520     {
521         this.packagingIncludes = packagingIncludes;
522     }
523 
524     private static File buildDestinationFile( File buildDir, String uri )
525     {
526         return new File( buildDir, uri );
527     }
528 
529     private void includeCustomManifestFile()
530     {
531         if ( manifestFile == null )
532         {
533             manifestFile = new File( getWorkDirectory(), "META-INF/MANIFEST.MF" );
534         }
535 
536         if ( !manifestFile.exists() )
537         {
538             getLog().info( "Could not find manifest file: " + manifestFile + " - Generating one" );
539         }
540         else
541         {
542             getLog().info( "Including custom manifest file [" + manifestFile + "]" );
543             archive.setManifestFile( manifestFile );
544         }
545     }
546 
547     /**
548      * Returns the EAR file to generate, based on an optional classifier.
549      *
550      * @param basedir    the output directory
551      * @param finalName  the name of the ear file
552      * @param classifier an optional classifier
553      * @return the EAR file to generate
554      */
555     private static File getEarFile( String basedir, String finalName, String classifier )
556     {
557         if ( classifier == null )
558         {
559             classifier = "";
560         }
561         else if ( classifier.trim().length() > 0 && !classifier.startsWith( "-" ) )
562         {
563             classifier = "-" + classifier;
564         }
565 
566         return new File( basedir, finalName + classifier + ".ear" );
567     }
568 
569     /**
570      * Returns a list of filenames that should be copied
571      * over to the destination directory.
572      *
573      * @param sourceDir the directory to be scanned
574      * @return the array of filenames, relative to the sourceDir
575      */
576     private String[] getEarFiles( File sourceDir )
577     {
578         DirectoryScanner scanner = new DirectoryScanner();
579         scanner.setBasedir( sourceDir );
580         scanner.setExcludes( getExcludes() );
581         scanner.addDefaultExcludes();
582 
583         scanner.setIncludes( getIncludes() );
584 
585         scanner.scan();
586 
587         return scanner.getIncludedFiles();
588     }
589 
590     /**
591      * Unpacks the module into the EAR structure.
592      *
593      * @param source  File to be unpacked.
594      * @param destDir Location where to put the unpacked files.
595      */
596     public void unpack( File source, File destDir )
597         throws NoSuchArchiverException, IOException, ArchiverException
598     {
599         UnArchiver unArchiver = archiverManager.getUnArchiver( "zip" );
600         unArchiver.setSourceFile( source );
601         unArchiver.setDestDirectory( destDir );
602 
603         // Extract the module
604         unArchiver.extract();
605     }
606 
607     /**
608      * Returns the {@link JarArchiver} implementation used
609      * to package the EAR file.
610      * <p/>
611      * By default the archiver is obtained from the Plexus container.
612      *
613      * @return the archiver
614      */
615     protected JarArchiver getJarArchiver()
616     {
617         return jarArchiver;
618     }
619 
620     private void copyFile( File source, File target )
621         throws MavenFilteringException, IOException, MojoExecutionException
622     {
623         if ( filtering && !isNonFilteredExtension( source.getName() ) )
624         {
625             // Silly that we have to do this ourselves
626             if ( target.getParentFile() != null && !target.getParentFile().exists() )
627             {
628                 target.getParentFile().mkdirs();
629             }
630             mavenFileFilter.copyFile( source, target, true, getFilterWrappers(), null );
631         }
632         else
633         {
634             FileUtils.copyFile( source, target );
635         }
636     }
637 
638     public boolean isNonFilteredExtension( String fileName )
639     {
640         return !mavenResourcesFiltering.filteredFileExtension( fileName, nonFilteredFileExtensions );
641     }
642 
643     private List getFilterWrappers()
644         throws MojoExecutionException
645     {
646         if ( filterWrappers == null )
647         {
648             try
649             {
650                 MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
651                 mavenResourcesExecution.setEscapeString( escapeString );
652                 filterWrappers =
653                     mavenFileFilter.getDefaultFilterWrappers( project, filters, escapedBackslashesInFilePath,
654                                                               this.session, mavenResourcesExecution );
655             }
656             catch ( MavenFilteringException e )
657             {
658                 getLog().error( "Fail to build filtering wrappers " + e.getMessage() );
659                 throw new MojoExecutionException( e.getMessage(), e );
660             }
661         }
662         return filterWrappers;
663     }
664 
665     private void changeManifestClasspath( EarModule module, File original )
666         throws MojoFailureException
667     {
668         try
669         {
670             File workDirectory;
671 
672             // Handle the case that the destination might be a directory (project-038)
673             if ( original.isFile() )
674             {
675                 // Create a temporary work directory
676                 workDirectory =
677                     new File( new File( generatedDescriptorLocation, "temp" ), module.getArtifact().getArtifactId() );
678                 workDirectory.mkdirs();
679                 getLog().debug( "Created a temporary work directory: " + workDirectory.getAbsolutePath() );
680 
681                 // Unpack the archive to a temporary work directory
682                 zipUnArchiver.setSourceFile( original );
683                 zipUnArchiver.setDestDirectory( workDirectory );
684                 zipUnArchiver.extract();
685             }
686             else
687             {
688                 workDirectory = original;
689             }
690 
691             // Create a META-INF/MANIFEST.MF file if it doesn't exist (project-038)
692             File metaInfDirectory = new File( workDirectory, "META-INF" );
693             boolean newMetaInfCreated = metaInfDirectory.mkdirs();
694             if ( newMetaInfCreated )
695             {
696                 getLog().debug(
697                     "This project did not have a META-INF directory before, so a new directory was created." );
698             }
699             File manifestFile = new File( metaInfDirectory, "MANIFEST.MF" );
700             boolean newManifestCreated = manifestFile.createNewFile();
701             if ( newManifestCreated )
702             {
703                 getLog().debug(
704                     "This project did not have a META-INF/MANIFEST.MF file before, so a new file was created." );
705             }
706 
707             // Read the manifest from disk
708             Manifest mf = new Manifest( new FileReader( manifestFile ) );
709             Attribute classPath = mf.getMainSection().getAttribute( "Class-Path" );
710             List<String> classPathElements = new ArrayList<String>();
711 
712             if ( classPath != null )
713             {
714                 classPathElements.addAll( Arrays.asList( classPath.getValue().split( " " ) ) );
715             }
716             else
717             {
718                 classPath = new Attribute( "Class-Path", "" );
719                 mf.getMainSection().addConfiguredAttribute( classPath );
720             }
721 
722             // Modify the classpath entries in the manifest
723             for ( EarModule o : getModules() )
724             {
725                 if ( o instanceof JarModule )
726                 {
727                     JarModule jm = (JarModule) o;
728 
729                     if ( module.getLibDir() != null )
730                     {
731                         File artifact =
732                             new File( new File( workDirectory, module.getLibDir() ), jm.getBundleFileName() );
733 
734                         if ( artifact.exists() )
735                         {
736                             if ( !artifact.delete() )
737                             {
738                                 getLog().error( "Could not delete '" + artifact + "'" );
739                             }
740                         }
741                     }
742 
743                     if ( classPathElements.contains( jm.getBundleFileName() ) )
744                     {
745                         classPathElements.set( classPathElements.indexOf( jm.getBundleFileName() ), jm.getUri() );
746                     }
747                     else
748                     {
749                         classPathElements.add( jm.getUri() );
750                     }
751                 }
752             }
753             classPath.setValue( StringUtils.join( classPathElements.iterator(), " " ) );
754 
755             // Write the manifest to disk
756             PrintWriter pw = new PrintWriter( manifestFile );
757             mf.write( pw );
758             pw.close();
759 
760             if ( original.isFile() )
761             {
762                 // Pack up the archive again from the work directory
763                 if ( !original.delete() )
764                 {
765                     getLog().error( "Could not delete original artifact file " + original );
766                 }
767 
768                 getLog().debug( "Zipping module" );
769                 zipArchiver.setDestFile( original );
770                 zipArchiver.addDirectory( workDirectory );
771                 zipArchiver.createArchive();
772             }
773         }
774         catch ( ManifestException e )
775         {
776             throw new MojoFailureException( e.getMessage() );
777         }
778         catch ( ZipException e )
779         {
780             throw new MojoFailureException( e.getMessage() );
781         }
782         catch ( IOException e )
783         {
784             throw new MojoFailureException( e.getMessage() );
785         }
786         catch ( ArchiverException e )
787         {
788             throw new MojoFailureException( e.getMessage() );
789         }
790     }
791 }