View Javadoc

1   package org.apache.tomcat.maven.plugin.tomcat7.run;
2   /*
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   */
20  
21  import org.apache.commons.compress.archivers.ArchiveException;
22  import org.apache.commons.compress.archivers.ArchiveOutputStream;
23  import org.apache.commons.compress.archivers.ArchiveStreamFactory;
24  import org.apache.commons.compress.archivers.jar.JarArchiveEntry;
25  import org.apache.commons.io.FileUtils;
26  import org.apache.commons.io.IOUtils;
27  import org.apache.commons.lang.StringUtils;
28  import org.apache.maven.artifact.Artifact;
29  import org.apache.maven.artifact.factory.ArtifactFactory;
30  import org.apache.maven.artifact.repository.ArtifactRepository;
31  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
32  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
33  import org.apache.maven.artifact.resolver.ArtifactResolver;
34  import org.apache.maven.model.Dependency;
35  import org.apache.maven.plugin.MojoExecutionException;
36  import org.apache.maven.plugin.MojoFailureException;
37  import org.apache.maven.plugins.annotations.Component;
38  import org.apache.maven.plugins.annotations.Parameter;
39  import org.apache.maven.project.MavenProject;
40  import org.apache.maven.project.MavenProjectHelper;
41  import org.apache.tomcat.maven.plugin.tomcat7.AbstractTomcat7Mojo;
42  import org.apache.tomcat.maven.runner.Tomcat7Runner;
43  import org.apache.tomcat.maven.runner.Tomcat7RunnerCli;
44  import org.codehaus.plexus.archiver.jar.Manifest;
45  import org.codehaus.plexus.archiver.jar.ManifestException;
46  import org.codehaus.plexus.util.DirectoryScanner;
47  import org.codehaus.plexus.util.SelectorUtils;
48  
49  import java.io.File;
50  import java.io.FileInputStream;
51  import java.io.FileOutputStream;
52  import java.io.IOException;
53  import java.io.OutputStream;
54  import java.io.PrintWriter;
55  import java.util.ArrayList;
56  import java.util.Enumeration;
57  import java.util.Iterator;
58  import java.util.List;
59  import java.util.Properties;
60  import java.util.jar.JarEntry;
61  import java.util.jar.JarFile;
62  
63  /**
64   * @author Olivier Lamy
65   * @since 2.0
66   */
67  public abstract class AbstractExecWarMojo
68      extends AbstractTomcat7Mojo
69  {
70  
71      @Parameter( defaultValue = "${project.artifact}", required = true, readonly = true )
72      protected Artifact projectArtifact;
73  
74      /**
75       * The maven project.
76       */
77      @Parameter( defaultValue = "${project}", required = true, readonly = true )
78      protected MavenProject project;
79  
80      @Parameter( defaultValue = "${plugin.artifacts}", required = true )
81      protected List<Artifact> pluginArtifacts;
82  
83      @Parameter( defaultValue = "${project.build.directory}" )
84      protected File buildDirectory;
85  
86      /**
87       * Path under {@link #buildDirectory} where this mojo may do temporary work.
88       */
89      @Parameter( defaultValue = "${project.build.directory}/tomcat7-maven-plugin-exec" )
90      private File pluginWorkDirectory;
91  
92      @Parameter( property = "maven.tomcat.exec.war.tomcatConf", defaultValue = "src/main/tomcatconf" )
93      protected File tomcatConfigurationFilesDirectory;
94  
95      @Parameter( defaultValue = "src/main/tomcatconf/server.xml", property = "maven.tomcat.exec.war.serverXml" )
96      protected File serverXml;
97  
98      /**
99       * Name of the generated exec JAR.
100      */
101     @Parameter( property = "tomcat.jar.finalName",
102                 defaultValue = "${project.artifactId}-${project.version}-war-exec.jar", required = true )
103     protected String finalName;
104 
105     /**
106      * Skip the execution
107      *
108      * @since 2.2
109      */
110     @Parameter( property = "maven.tomcat.skip", defaultValue = "false" )
111     private boolean skip;
112 
113     /**
114      * The webapp context path to use for the web application being run.
115      * The name to store webapp in exec jar. Do not use /
116      */
117     @Parameter( property = "maven.tomcat.path", defaultValue = "${project.artifactId}", required = true )
118     protected String path;
119 
120     @Parameter
121     protected List<WarRunDependency> warRunDependencies;
122 
123     @Component
124     protected ArtifactResolver artifactResolver;
125 
126     /**
127      * Maven Artifact Factory component.
128      */
129     @Component
130     protected ArtifactFactory artifactFactory;
131 
132     /**
133      * Location of the local repository.
134      */
135     @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
136     protected ArtifactRepository local;
137 
138     /**
139      * List of Remote Repositories used by the resolver
140      */
141     @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
142     protected List<ArtifactRepository> remoteRepos;
143 
144     @Component
145     protected MavenProjectHelper projectHelper;
146 
147     /**
148      * Attach or not the generated artifact to the build (use true if you want to install or deploy it)
149      */
150     @Parameter( property = "maven.tomcat.exec.war.attachArtifact", defaultValue = "true", required = true )
151     protected boolean attachArtifact;
152 
153 
154     /**
155      * the classifier to use for the attached/generated artifact
156      */
157     @Parameter( property = "maven.tomcat.exec.war.attachArtifactClassifier", defaultValue = "exec-war",
158                 required = true )
159     protected String attachArtifactClassifier;
160 
161 
162     /**
163      * the type to use for the attached/generated artifact
164      */
165     @Parameter( property = "maven.tomcat.exec.war.attachArtifactType", defaultValue = "jar", required = true )
166     protected String attachArtifactClassifierType;
167 
168     /**
169      * to enable naming when starting tomcat
170      */
171     @Parameter( property = "maven.tomcat.exec.war.enableNaming", defaultValue = "false", required = true )
172     protected boolean enableNaming;
173 
174     /**
175      * see http://tomcat.apache.org/tomcat-7.0-doc/config/valve.html
176      */
177     @Parameter( property = "maven.tomcat.exec.war.accessLogValveFormat", defaultValue = "%h %l %u %t %r %s %b %I %D",
178                 required = true )
179     protected String accessLogValveFormat;
180 
181     /**
182      * list of extra dependencies to add in the standalone tomcat jar: your jdbc driver, mail.jar etc..
183      * <b>Those dependencies will be in root classloader.</b>
184      */
185     @Parameter
186     protected List<ExtraDependency> extraDependencies;
187 
188     /**
189      * list of extra resources to add in the standalone tomcat jar: your logger configuration etc
190      */
191     @Parameter
192     protected List<ExtraResource> extraResources;
193 
194     /**
195      * Main class to use for starting the standalone jar.
196      */
197     @Parameter( property = "maven.tomcat.exec.war.mainClass",
198                 defaultValue = "org.apache.tomcat.maven.runner.Tomcat7RunnerCli", required = true )
199     protected String mainClass;
200 
201     /**
202      * which connector protocol to use HTTP/1.1 or org.apache.coyote.http11.Http11NioProtocol
203      */
204     @Parameter( property = "maven.tomcat.exec.war.connectorHttpProtocol", defaultValue = "HTTP/1.1", required = true )
205     protected String connectorHttpProtocol;
206 
207     /**
208      * configure a default http port for the standalone jar
209      *
210      * @since 2.2
211      */
212     @Parameter( property = "maven.tomcat.exec.war.httpPort" )
213     protected String httpPort;
214 
215     /**
216      * File patterns to exclude from extraDependencies
217      *
218      * @since 2.2
219      */
220     @Parameter
221     protected String[] excludes;
222 
223     public void execute()
224         throws MojoExecutionException, MojoFailureException
225     {
226         if ( this.skip )
227         {
228             getLog().info( "skip execution" );
229             return;
230         }
231         //project.addAttachedArtifact(  );
232         File warExecFile = new File( buildDirectory, finalName );
233         if ( warExecFile.exists() )
234         {
235             warExecFile.delete();
236         }
237 
238         File execWarJar = new File( buildDirectory, finalName );
239 
240         FileOutputStream execWarJarOutputStream = null;
241         ArchiveOutputStream os = null;
242         File tmpPropertiesFile = null;
243         File tmpManifestFile = null;
244         FileOutputStream tmpPropertiesFileOutputStream = null;
245         PrintWriter tmpManifestWriter = null;
246 
247         try
248         {
249 
250             tmpPropertiesFile = new File( buildDirectory, "war-exec.properties" );
251             if ( tmpPropertiesFile.exists() )
252             {
253                 tmpPropertiesFile.delete();
254             }
255             tmpPropertiesFile.getParentFile().mkdirs();
256 
257             tmpManifestFile = new File( buildDirectory, "war-exec.manifest" );
258             if ( tmpManifestFile.exists() )
259             {
260                 tmpManifestFile.delete();
261             }
262             tmpPropertiesFileOutputStream = new FileOutputStream( tmpPropertiesFile );
263             execWarJar.getParentFile().mkdirs();
264             execWarJar.createNewFile();
265             execWarJarOutputStream = new FileOutputStream( execWarJar );
266 
267             tmpManifestWriter = new PrintWriter( tmpManifestFile );
268 
269             // store :
270             //* wars in the root: foo.war
271             //* tomcat jars
272             //* file tomcat.standalone.properties with possible values :
273             //   * useServerXml=true/false to use directly the one provided
274             //   * enableNaming=true/false
275             //   * wars=foo.war|contextpath;bar.war  ( |contextpath is optionnal if empty use the war name )
276             //   * accessLogValveFormat=
277             //   * connectorhttpProtocol: HTTP/1.1 or org.apache.coyote.http11.Http11NioProtocol
278             //* optionnal: conf/ with usual tomcat configuration files
279             //* MANIFEST with Main-Class
280 
281             Properties properties = new Properties();
282 
283             properties.put( Tomcat7Runner.ARCHIVE_GENERATION_TIMESTAMP_KEY,
284                             Long.toString( System.currentTimeMillis() ) );
285             properties.put( Tomcat7Runner.ENABLE_NAMING_KEY, Boolean.toString( enableNaming ) );
286             properties.put( Tomcat7Runner.ACCESS_LOG_VALVE_FORMAT_KEY, accessLogValveFormat );
287             properties.put( Tomcat7Runner.HTTP_PROTOCOL_KEY, connectorHttpProtocol );
288 
289             if ( httpPort != null )
290             {
291                 properties.put( Tomcat7Runner.HTTP_PORT_KEY, httpPort );
292             }
293 
294             os = new ArchiveStreamFactory().createArchiveOutputStream( ArchiveStreamFactory.JAR,
295                                                                        execWarJarOutputStream );
296 
297             if ( "war".equals( project.getPackaging() ) )
298             {
299 
300                 os.putArchiveEntry( new JarArchiveEntry( StringUtils.removeStart( path, "/" ) + ".war" ) );
301                 IOUtils.copy( new FileInputStream( projectArtifact.getFile() ), os );
302                 os.closeArchiveEntry();
303 
304                 properties.put( Tomcat7Runner.WARS_KEY, StringUtils.removeStart( path, "/" ) + ".war|" + path );
305             }
306             else if ( warRunDependencies != null && !warRunDependencies.isEmpty() )
307             {
308                 for ( WarRunDependency warRunDependency : warRunDependencies )
309                 {
310                     if ( warRunDependency.dependency != null )
311                     {
312                         Dependency dependency = warRunDependency.dependency;
313                         String version = dependency.getVersion();
314                         if ( StringUtils.isEmpty( version ) )
315                         {
316                             version = findArtifactVersion( dependency );
317                         }
318 
319                         if ( StringUtils.isEmpty( version ) )
320                         {
321                             throw new MojoExecutionException(
322                                 "Dependency '" + dependency.getGroupId() + "':'" + dependency.getArtifactId()
323                                     + "' does not have version specified" );
324                         }
325                         Artifact artifact = artifactFactory.createArtifactWithClassifier( dependency.getGroupId(),
326                                                                                           dependency.getArtifactId(),
327                                                                                           version,
328                                                                                           dependency.getType(),
329                                                                                           dependency.getClassifier() );
330 
331                         artifactResolver.resolve( artifact, this.remoteRepos, this.local );
332 
333                         File warFileToBundle = new File( resolvePluginWorkDir(), artifact.getFile().getName() );
334                         FileUtils.copyFile( artifact.getFile(), warFileToBundle );
335 
336                         if ( warRunDependency.contextXml != null )
337                         {
338                             warFileToBundle = addContextXmlToWar( warRunDependency.contextXml, warFileToBundle );
339                         }
340                         final String warFileName = artifact.getFile().getName();
341                         os.putArchiveEntry( new JarArchiveEntry( warFileName ) );
342                         IOUtils.copy( new FileInputStream( warFileToBundle ), os );
343                         os.closeArchiveEntry();
344                         String propertyWarValue = properties.getProperty( Tomcat7Runner.WARS_KEY );
345                         String contextPath =
346                             StringUtils.isEmpty( warRunDependency.contextPath ) ? "/" : warRunDependency.contextPath;
347                         if ( propertyWarValue != null )
348                         {
349                             properties.put( Tomcat7Runner.WARS_KEY,
350                                             propertyWarValue + ";" + warFileName + "|" + contextPath );
351                         }
352                         else
353                         {
354                             properties.put( Tomcat7Runner.WARS_KEY, warFileName + "|" + contextPath );
355                         }
356                     }
357                 }
358             }
359 
360             if ( serverXml != null && serverXml.exists() )
361             {
362                 os.putArchiveEntry( new JarArchiveEntry( "conf/server.xml" ) );
363                 IOUtils.copy( new FileInputStream( serverXml ), os );
364                 os.closeArchiveEntry();
365                 properties.put( Tomcat7Runner.USE_SERVER_XML_KEY, Boolean.TRUE.toString() );
366             }
367             else
368             {
369                 properties.put( Tomcat7Runner.USE_SERVER_XML_KEY, Boolean.FALSE.toString() );
370             }
371 
372             os.putArchiveEntry( new JarArchiveEntry( "conf/web.xml" ) );
373             IOUtils.copy( getClass().getResourceAsStream( "/conf/web.xml" ), os );
374             os.closeArchiveEntry();
375 
376             properties.store( tmpPropertiesFileOutputStream, "created by Apache Tomcat Maven plugin" );
377 
378             tmpPropertiesFileOutputStream.flush();
379             tmpPropertiesFileOutputStream.close();
380 
381             os.putArchiveEntry( new JarArchiveEntry( Tomcat7RunnerCli.STAND_ALONE_PROPERTIES_FILENAME ) );
382             IOUtils.copy( new FileInputStream( tmpPropertiesFile ), os );
383             os.closeArchiveEntry();
384 
385             // add tomcat classes
386             for ( Artifact pluginArtifact : pluginArtifacts )
387             {
388                 if ( StringUtils.equals( "org.apache.tomcat", pluginArtifact.getGroupId() ) || StringUtils.equals(
389                     "org.apache.tomcat.embed", pluginArtifact.getGroupId() ) || StringUtils.equals(
390                     "org.eclipse.jdt.core.compiler", pluginArtifact.getGroupId() ) || StringUtils.equals( "commons-cli",
391                                                                                                           pluginArtifact.getArtifactId() )
392                     || StringUtils.equals( "tomcat7-war-runner", pluginArtifact.getArtifactId() ) )
393                 {
394                     JarFile jarFile = new JarFile( pluginArtifact.getFile() );
395                     extractJarToArchive( jarFile, os, null );
396                 }
397             }
398 
399             // add extra dependencies
400             if ( extraDependencies != null && !extraDependencies.isEmpty() )
401             {
402                 for ( Dependency dependency : extraDependencies )
403                 {
404                     String version = dependency.getVersion();
405                     if ( StringUtils.isEmpty( version ) )
406                     {
407                         version = findArtifactVersion( dependency );
408                     }
409 
410                     if ( StringUtils.isEmpty( version ) )
411                     {
412                         throw new MojoExecutionException(
413                             "Dependency '" + dependency.getGroupId() + "':'" + dependency.getArtifactId()
414                                 + "' does not have version specified" );
415                     }
416 
417                     // String groupId, String artifactId, String version, String scope, String type
418                     Artifact artifact =
419                         artifactFactory.createArtifact( dependency.getGroupId(), dependency.getArtifactId(), version,
420                                                         dependency.getScope(), dependency.getType() );
421 
422                     artifactResolver.resolve( artifact, this.remoteRepos, this.local );
423                     JarFile jarFile = new JarFile( artifact.getFile() );
424                     extractJarToArchive( jarFile, os, this.excludes );
425                 }
426             }
427 
428             Manifest manifest = new Manifest();
429 
430             Manifest.Attribute mainClassAtt = new Manifest.Attribute();
431             mainClassAtt.setName( "Main-Class" );
432             mainClassAtt.setValue( mainClass );
433             manifest.addConfiguredAttribute( mainClassAtt );
434 
435             manifest.write( tmpManifestWriter );
436             tmpManifestWriter.flush();
437             tmpManifestWriter.close();
438 
439             os.putArchiveEntry( new JarArchiveEntry( "META-INF/MANIFEST.MF" ) );
440             IOUtils.copy( new FileInputStream( tmpManifestFile ), os );
441             os.closeArchiveEntry();
442 
443             if ( attachArtifact )
444             {
445                 //MavenProject project, String artifactType, String artifactClassifier, File artifactFile
446                 projectHelper.attachArtifact( project, attachArtifactClassifierType, attachArtifactClassifier,
447                                               execWarJar );
448             }
449 
450             if ( extraResources != null )
451             {
452                 for ( ExtraResource extraResource : extraResources )
453                 {
454 
455                     DirectoryScanner directoryScanner = new DirectoryScanner();
456                     directoryScanner.setBasedir( extraResource.getDirectory() );
457                     directoryScanner.addDefaultExcludes();
458                     directoryScanner.setExcludes( toStringArray( extraResource.getExcludes() ) );
459                     directoryScanner.setIncludes( toStringArray( extraResource.getIncludes() ) );
460                     directoryScanner.scan();
461                     for ( String includeFile : directoryScanner.getIncludedFiles() )
462                     {
463                         getLog().debug( "include file:" + includeFile );
464                         os.putArchiveEntry( new JarArchiveEntry( includeFile ) );
465                         IOUtils.copy( new FileInputStream( new File( extraResource.getDirectory(), includeFile ) ),
466                                       os );
467                         os.closeArchiveEntry();
468                     }
469                 }
470             }
471 
472             if ( tomcatConfigurationFilesDirectory != null && tomcatConfigurationFilesDirectory.exists() )
473             {
474                 // Because its the tomcat default dir for configs
475                 String aConfigOutputDir = "conf/";
476                 copyDirectoryContentIntoArchive( tomcatConfigurationFilesDirectory, aConfigOutputDir, os );
477             }
478 
479         }
480         catch ( ManifestException e )
481         {
482             throw new MojoExecutionException( e.getMessage(), e );
483         }
484         catch ( IOException e )
485         {
486             throw new MojoExecutionException( e.getMessage(), e );
487         }
488         catch ( ArchiveException e )
489         {
490             throw new MojoExecutionException( e.getMessage(), e );
491         }
492         catch ( ArtifactNotFoundException e )
493         {
494             throw new MojoExecutionException( e.getMessage(), e );
495         }
496         catch ( ArtifactResolutionException e )
497         {
498             throw new MojoExecutionException( e.getMessage(), e );
499         }
500         finally
501         {
502             IOUtils.closeQuietly( os );
503             IOUtils.closeQuietly( tmpManifestWriter );
504             IOUtils.closeQuietly( execWarJarOutputStream );
505             IOUtils.closeQuietly( tmpPropertiesFileOutputStream );
506         }
507     }
508 
509     protected String findArtifactVersion( Dependency dependency )
510     {
511         // search in project.dependencies
512         for ( Dependency projectDependency : (List<Dependency>) this.project.getDependencies() )
513         {
514             if ( sameDependencyWithoutVersion( dependency, projectDependency ) )
515             {
516                 return projectDependency.getVersion();
517             }
518         }
519 
520         // search in project.dependencies
521         for ( Dependency projectDependency : (List<Dependency>) this.project.getDependencyManagement().getDependencies() )
522         {
523             if ( sameDependencyWithoutVersion( dependency, projectDependency ) )
524             {
525                 return projectDependency.getVersion();
526             }
527         }
528 
529         return null;
530     }
531 
532     protected boolean sameDependencyWithoutVersion( Dependency that, Dependency dependency )
533     {
534         return StringUtils.equals( that.getGroupId(), dependency.getGroupId() ) && StringUtils.equals(
535             that.getArtifactId(), dependency.getArtifactId() );
536     }
537 
538     protected void copyDirectoryContentIntoArchive( File sourceFolder, String destinationPath,
539                                                     ArchiveOutputStream archiveOutputStream )
540         throws IOException
541     {
542 
543         // Scan the directory
544         DirectoryScanner directoryScanner = new DirectoryScanner();
545         directoryScanner.setBasedir( sourceFolder );
546         directoryScanner.addDefaultExcludes();
547         directoryScanner.scan();
548 
549         // Each File
550         for ( String includeFileName : directoryScanner.getIncludedFiles() )
551         {
552             getLog().debug( "include configuration file : " + destinationPath + includeFileName );
553             File inputFile = new File( sourceFolder, includeFileName );
554 
555             FileInputStream sourceFileInputStream = null;
556             try
557             {
558                 sourceFileInputStream = new FileInputStream( inputFile );
559 
560                 archiveOutputStream.putArchiveEntry( new JarArchiveEntry( destinationPath + includeFileName ) );
561                 IOUtils.copy( sourceFileInputStream, archiveOutputStream );
562                 archiveOutputStream.closeArchiveEntry();
563             }
564             finally
565             {
566                 IOUtils.closeQuietly( sourceFileInputStream );
567             }
568         }
569 
570     }
571 
572     /**
573      * Resolves the plugin work dir as a sub directory of {@link #buildDirectory}, creating it if it does not exist.
574      *
575      * @return File representing the resolved plugin work dir
576      * @throws MojoExecutionException if the plugin work dir cannot be created
577      */
578     protected File resolvePluginWorkDir()
579         throws MojoExecutionException
580     {
581         if ( !pluginWorkDirectory.exists() && !pluginWorkDirectory.mkdirs() )
582         {
583             throw new MojoExecutionException(
584                 "Could not create plugin work directory at " + pluginWorkDirectory.getAbsolutePath() );
585         }
586 
587         return pluginWorkDirectory;
588 
589     }
590 
591     protected String[] toStringArray( List list )
592     {
593         if ( list == null || list.isEmpty() )
594         {
595             return new String[0];
596         }
597         List<String> res = new ArrayList<String>( list.size() );
598 
599         for ( Iterator ite = list.iterator(); ite.hasNext(); )
600         {
601             res.add( (String) ite.next() );
602         }
603         return res.toArray( new String[res.size()] );
604     }
605 
606 
607     /**
608      * return file can be deleted
609      */
610     protected File addContextXmlToWar( File contextXmlFile, File warFile )
611         throws IOException, ArchiveException
612     {
613         ArchiveOutputStream os = null;
614         OutputStream warOutputStream = null;
615         File tmpWar = File.createTempFile( "tomcat", "war-exec" );
616         tmpWar.deleteOnExit();
617 
618         try
619         {
620             warOutputStream = new FileOutputStream( tmpWar );
621             os = new ArchiveStreamFactory().createArchiveOutputStream( ArchiveStreamFactory.JAR, warOutputStream );
622             os.putArchiveEntry( new JarArchiveEntry( "META-INF/context.xml" ) );
623             IOUtils.copy( new FileInputStream( contextXmlFile ), os );
624             os.closeArchiveEntry();
625 
626             JarFile jarFile = new JarFile( warFile );
627             extractJarToArchive( jarFile, os, null );
628             os.flush();
629         }
630         finally
631         {
632             IOUtils.closeQuietly( os );
633             IOUtils.closeQuietly( warOutputStream );
634         }
635         return tmpWar;
636     }
637 
638     /**
639      * Copy the contents of a jar file to another archive
640      *
641      * @param file The input jar file
642      * @param os   The output archive
643      * @throws IOException
644      */
645     protected void extractJarToArchive( JarFile file, ArchiveOutputStream os, String[] excludes )
646         throws IOException
647     {
648         Enumeration<? extends JarEntry> entries = file.entries();
649         while ( entries.hasMoreElements() )
650         {
651             JarEntry j = entries.nextElement();
652 
653             if ( excludes != null && excludes.length > 0 )
654             {
655                 for ( String exclude : excludes )
656                 {
657                     if ( SelectorUtils.match( exclude, j.getName() ) )
658                     {
659                         continue;
660                     }
661                 }
662             }
663 
664             if ( StringUtils.equalsIgnoreCase( j.getName(), "META-INF/MANIFEST.MF" ) )
665             {
666                 continue;
667             }
668             os.putArchiveEntry( new JarArchiveEntry( j.getName() ) );
669             IOUtils.copy( file.getInputStream( j ), os );
670             os.closeArchiveEntry();
671         }
672         if ( file != null )
673         {
674             file.close();
675         }
676     }
677 }