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 }