1 package org.apache.maven.plugins.ear;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.OutputStreamWriter;
27 import java.nio.charset.StandardCharsets;
28 import java.nio.file.FileVisitResult;
29 import java.nio.file.Files;
30 import java.nio.file.Path;
31 import java.nio.file.Paths;
32 import java.nio.file.SimpleFileVisitor;
33 import java.nio.file.attribute.BasicFileAttributes;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.Date;
38 import java.util.List;
39 import java.util.Objects;
40
41 import org.apache.maven.archiver.MavenArchiveConfiguration;
42 import org.apache.maven.archiver.MavenArchiver;
43 import org.apache.maven.artifact.DependencyResolutionRequiredException;
44 import org.apache.maven.execution.MavenSession;
45 import org.apache.maven.plugin.MojoExecutionException;
46 import org.apache.maven.plugin.MojoFailureException;
47 import org.apache.maven.plugins.annotations.Component;
48 import org.apache.maven.plugins.annotations.LifecyclePhase;
49 import org.apache.maven.plugins.annotations.Mojo;
50 import org.apache.maven.plugins.annotations.Parameter;
51 import org.apache.maven.plugins.annotations.ResolutionScope;
52 import org.apache.maven.plugins.ear.util.EarMavenArchiver;
53 import org.apache.maven.plugins.ear.util.JavaEEVersion;
54 import org.apache.maven.project.MavenProjectHelper;
55 import org.apache.maven.shared.filtering.MavenFileFilter;
56 import org.apache.maven.shared.filtering.MavenFilteringException;
57 import org.apache.maven.shared.filtering.MavenResourcesExecution;
58 import org.apache.maven.shared.filtering.MavenResourcesFiltering;
59 import org.apache.maven.shared.utils.io.FileUtils;
60 import org.codehaus.plexus.archiver.Archiver;
61 import org.codehaus.plexus.archiver.ArchiverException;
62 import org.codehaus.plexus.archiver.UnArchiver;
63 import org.codehaus.plexus.archiver.ear.EarArchiver;
64 import org.codehaus.plexus.archiver.jar.JarArchiver;
65 import org.codehaus.plexus.archiver.jar.Manifest;
66 import org.codehaus.plexus.archiver.jar.Manifest.Attribute;
67 import org.codehaus.plexus.archiver.jar.ManifestException;
68 import org.codehaus.plexus.archiver.manager.ArchiverManager;
69 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
70 import org.codehaus.plexus.archiver.zip.ZipArchiver;
71 import org.codehaus.plexus.archiver.zip.ZipUnArchiver;
72 import org.codehaus.plexus.components.io.filemappers.FileMapper;
73 import org.codehaus.plexus.util.DirectoryScanner;
74 import org.codehaus.plexus.util.StringUtils;
75
76
77
78
79
80
81
82 @Mojo( name = "ear", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, requiresDependencyResolution = ResolutionScope.TEST )
83
84 public class EarMojo
85 extends AbstractEarMojo
86 {
87
88
89
90 @Parameter( defaultValue = "${basedir}/src/main/application", required = true )
91 private File earSourceDirectory;
92
93
94
95
96 @Parameter( alias = "includes", defaultValue = "**" )
97 private String earSourceIncludes;
98
99
100
101
102 @Parameter( alias = "excludes" )
103 private String earSourceExcludes;
104
105
106
107
108
109
110 @Parameter( defaultValue = "false" )
111 private boolean filtering;
112
113
114
115
116
117
118 @Parameter
119 private List<String> filters;
120
121
122
123
124
125
126 @Parameter
127 private List<String> nonFilteredFileExtensions;
128
129
130
131
132
133
134 @Parameter( defaultValue = "false" )
135 private boolean escapedBackslashesInFilePath;
136
137
138
139
140
141
142 @Parameter
143 protected String escapeString;
144
145
146
147
148
149
150
151
152 @Parameter( defaultValue = "false" )
153 private boolean skipClassPathModification;
154
155
156
157
158 @Parameter
159 private String applicationXml;
160
161
162
163
164 @Parameter( defaultValue = "${project.build.directory}", required = true )
165 private String outputDirectory;
166
167
168
169
170 @Parameter( defaultValue = "${project.build.finalName}", required = true, readonly = true )
171 private String finalName;
172
173
174
175
176 @Parameter
177 private String unpackTypes;
178
179
180
181
182 @Parameter
183 private String classifier;
184
185
186
187
188
189
190
191
192 @Parameter
193 private String packagingExcludes;
194
195
196
197
198
199
200
201
202 @Parameter
203 private String packagingIncludes;
204
205
206
207
208
209
210
211 @Parameter( defaultValue = "false" )
212 private boolean skinnyWars;
213
214
215
216
217 @Component( role = Archiver.class, hint = "ear" )
218 private EarArchiver earArchiver;
219
220
221
222
223 @Component( role = Archiver.class, hint = "jar" )
224 private JarArchiver jarArchiver;
225
226
227
228
229 @Component( role = Archiver.class, hint = "zip" )
230 private ZipArchiver zipArchiver;
231
232
233
234
235 @Component( role = UnArchiver.class, hint = "zip" )
236 private ZipUnArchiver zipUnArchiver;
237
238
239
240
241
242 @Parameter
243 private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
244
245
246
247
248
249
250
251
252 @Parameter( defaultValue = "${project.build.outputTimestamp}" )
253 private String outputTimestamp;
254
255
256
257 @Component
258 private MavenProjectHelper projectHelper;
259
260
261
262
263 @Component
264 private ArchiverManager archiverManager;
265
266
267
268 @Component( role = MavenFileFilter.class, hint = "default" )
269 private MavenFileFilter mavenFileFilter;
270
271
272
273 @Component( role = MavenResourcesFiltering.class, hint = "default" )
274 private MavenResourcesFiltering mavenResourcesFiltering;
275
276
277
278
279 @Parameter( defaultValue = "${session}", readonly = true, required = true )
280 private MavenSession session;
281
282 private List<FileUtils.FilterWrapper> filterWrappers;
283
284
285
286
287 @Parameter( defaultValue = "true" )
288 private boolean useJvmChmod = true;
289
290
291 public void execute()
292 throws MojoExecutionException, MojoFailureException
293 {
294
295 super.execute();
296
297 File earFile = getEarFile( outputDirectory, finalName, classifier );
298 MavenArchiver archiver = new EarMavenArchiver( getModules() );
299 File ddFile = new File( getWorkDirectory(), APPLICATION_XML_URI );
300
301 JarArchiver theArchiver;
302 if ( ddFile.exists() )
303 {
304 earArchiver.setAppxml( ddFile );
305 theArchiver = earArchiver;
306 }
307 else
308 {
309
310
311 theArchiver = jarArchiver;
312 }
313 getLog().debug( "Ear archiver implementation [" + theArchiver.getClass().getName() + "]" );
314 archiver.setArchiver( theArchiver );
315 archiver.setOutputFile( earFile );
316 archiver.setCreatedBy( "Maven EAR Plugin", "org.apache.maven.plugins", "maven-ear-plugin" );
317
318
319 Date reproducibleLastModifiedDate = archiver.configureReproducible( outputTimestamp );
320
321 zipArchiver.setUseJvmChmod( useJvmChmod );
322 if ( reproducibleLastModifiedDate != null )
323 {
324 zipArchiver.configureReproducible( reproducibleLastModifiedDate );
325 }
326 zipUnArchiver.setUseJvmChmod( useJvmChmod );
327
328 final JavaEEVersion javaEEVersion = JavaEEVersion.getJavaEEVersion( version );
329
330 final Collection<String> outdatedResources = initOutdatedResources();
331
332
333 List<String> unpackTypesList = createUnpackList();
334
335
336 copyModules( javaEEVersion, unpackTypesList, outdatedResources );
337
338
339 try
340 {
341 File earSourceDir = earSourceDirectory;
342
343 if ( earSourceDir.exists() )
344 {
345 getLog().info( "Copy ear sources to " + getWorkDirectory().getAbsolutePath() );
346 String[] fileNames = getEarFiles( earSourceDir );
347 for ( String fileName : fileNames )
348 {
349 copyFile( new File( earSourceDir, fileName ), new File( getWorkDirectory(), fileName ) );
350 outdatedResources.remove( Paths.get( fileName ).toString() );
351 }
352 }
353
354 if ( applicationXml != null && !"".equals( applicationXml ) )
355 {
356
357 getLog().info( "Including custom application.xml[" + applicationXml + "]" );
358 File metaInfDir = new File( getWorkDirectory(), META_INF );
359 copyFile( new File( applicationXml ), new File( metaInfDir, "/application.xml" ) );
360 outdatedResources.remove( Paths.get( "META-INF/application.xml" ).toString() );
361 }
362 }
363 catch ( IOException e )
364 {
365 throw new MojoExecutionException( "Error copying EAR sources", e );
366 }
367 catch ( MavenFilteringException e )
368 {
369 throw new MojoExecutionException( "Error filtering EAR sources", e );
370 }
371
372
373 if ( !ddFile.exists() && ( javaEEVersion.lt( JavaEEVersion.FIVE ) ) )
374 {
375 throw new MojoExecutionException( "Deployment descriptor: " + ddFile.getAbsolutePath()
376 + " does not exist." );
377 }
378
379 outdatedResources.remove( Paths.get( APPLICATION_XML_URI ).toString() );
380 if ( getJbossConfiguration() != null )
381 {
382 outdatedResources.remove( Paths.get( "META-INF/jboss-app.xml" ).toString() );
383 }
384
385 deleteOutdatedResources( outdatedResources );
386
387 try
388 {
389 getLog().debug( "Excluding " + Arrays.asList( getPackagingExcludes() ) + " from the generated EAR." );
390 getLog().debug( "Including " + Arrays.asList( getPackagingIncludes() ) + " in the generated EAR." );
391
392 archiver.getArchiver().addDirectory( getWorkDirectory(), getPackagingIncludes(), getPackagingExcludes() );
393
394 archiver.createArchive( session, getProject(), archive );
395 }
396 catch ( ManifestException | IOException | DependencyResolutionRequiredException e )
397 {
398 throw new MojoExecutionException( "Error assembling EAR", e );
399 }
400
401 if ( classifier != null )
402 {
403 projectHelper.attachArtifact( getProject(), "ear", classifier, earFile );
404 }
405 else
406 {
407 getProject().getArtifact().setFile( earFile );
408 }
409 }
410
411 private void copyModules( final JavaEEVersion javaEEVersion,
412 List<String> unpackTypesList,
413 Collection<String> outdatedResources )
414 throws MojoExecutionException, MojoFailureException
415 {
416 final Path workingDir = getWorkDirectory().toPath();
417
418 try
419 {
420 for ( EarModule module : getModules() )
421 {
422 final File sourceFile = module.getArtifact().getFile();
423 final File destinationFile = buildDestinationFile( getWorkDirectory(), module.getUri() );
424 if ( !sourceFile.isFile() )
425 {
426 throw new MojoExecutionException( "Cannot copy a directory: " + sourceFile.getAbsolutePath()
427 + "; Did you package/install " + module.getArtifact() + "?" );
428 }
429
430 if ( destinationFile.getCanonicalPath().equals( sourceFile.getCanonicalPath() ) )
431 {
432 getLog().info( "Skipping artifact [" + module + "], as it already exists at [" + module.getUri()
433 + "]" );
434
435 continue;
436 }
437
438
439
440 if ( ( unpackTypesList.contains( module.getType() )
441 && ( module.shouldUnpack() == null || module.shouldUnpack() ) )
442 || ( module.shouldUnpack() != null && module.shouldUnpack() ) )
443 {
444 getLog().info( "Copying artifact [" + module + "] to [" + module.getUri() + "] (unpacked)" );
445
446 if ( !destinationFile.mkdirs() )
447 {
448 throw new MojoExecutionException( "Error creating " + destinationFile );
449 }
450 unpack( sourceFile, destinationFile, outdatedResources );
451
452 if ( skinnyWars && module.changeManifestClasspath() )
453 {
454 changeManifestClasspath( module, destinationFile, javaEEVersion );
455 }
456 }
457 else
458 {
459 if ( sourceFile.lastModified() > destinationFile.lastModified() )
460 {
461 getLog().info( "Copying artifact [" + module + "] to [" + module.getUri() + "]" );
462 FileUtils.copyFile( sourceFile, destinationFile );
463
464 if ( skinnyWars && module.changeManifestClasspath() )
465 {
466 changeManifestClasspath( module, destinationFile, javaEEVersion );
467 }
468 }
469 else
470 {
471 getLog().debug( "Skipping artifact [" + module + "], as it is already up to date at ["
472 + module.getUri() + "]" );
473 }
474 outdatedResources.remove( workingDir.relativize( destinationFile.toPath() ).toString() );
475 }
476 }
477 }
478 catch ( IOException e )
479 {
480 throw new MojoExecutionException( "Error copying EAR modules", e );
481 }
482 catch ( ArchiverException e )
483 {
484 throw new MojoExecutionException( "Error unpacking EAR modules", e );
485 }
486 catch ( NoSuchArchiverException e )
487 {
488 throw new MojoExecutionException( "No Archiver found for EAR modules", e );
489 }
490 }
491
492 private List<String> createUnpackList()
493 throws MojoExecutionException
494 {
495 List<String> unpackTypesList = new ArrayList<String>();
496 if ( unpackTypes != null )
497 {
498 unpackTypesList = Arrays.asList( unpackTypes.split( "," ) );
499 for ( String type : unpackTypesList )
500 {
501 if ( !EarModuleFactory.STANDARD_ARTIFACT_TYPE.contains( type ) )
502 {
503 throw new MojoExecutionException( "Invalid type [" + type + "] supported types are "
504 + EarModuleFactory.STANDARD_ARTIFACT_TYPE );
505 }
506 }
507 getLog().debug( "Initialized unpack types " + unpackTypesList );
508 }
509 return unpackTypesList;
510 }
511
512
513
514
515 public String getApplicationXml()
516 {
517 return applicationXml;
518 }
519
520
521
522
523 public void setApplicationXml( String applicationXml )
524 {
525 this.applicationXml = applicationXml;
526 }
527
528
529
530
531
532
533 protected String[] getExcludes()
534 {
535 List<String> excludeList = new ArrayList<String>( FileUtils.getDefaultExcludesAsList() );
536 if ( earSourceExcludes != null && !"".equals( earSourceExcludes ) )
537 {
538 excludeList.addAll( Arrays.asList( StringUtils.split( earSourceExcludes, "," ) ) );
539 }
540
541
542 if ( getApplicationXml() != null && !"".equals( getApplicationXml() ) )
543 {
544 excludeList.add( "**/" + META_INF + "/application.xml" );
545 }
546
547 return excludeList.toArray( new String[excludeList.size()] );
548 }
549
550
551
552
553
554
555 protected String[] getIncludes()
556 {
557 return StringUtils.split( Objects.toString( earSourceIncludes, "" ), "," );
558 }
559
560
561
562
563 public String[] getPackagingExcludes()
564 {
565 if ( StringUtils.isEmpty( packagingExcludes ) )
566 {
567 return new String[0];
568 }
569 else
570 {
571 return StringUtils.split( packagingExcludes, "," );
572 }
573 }
574
575
576
577
578 public void setPackagingExcludes( String packagingExcludes )
579 {
580 this.packagingExcludes = packagingExcludes;
581 }
582
583
584
585
586 public String[] getPackagingIncludes()
587 {
588 if ( StringUtils.isEmpty( packagingIncludes ) )
589 {
590 return new String[] { "**" };
591 }
592 else
593 {
594 return StringUtils.split( packagingIncludes, "," );
595 }
596 }
597
598
599
600
601 public void setPackagingIncludes( String packagingIncludes )
602 {
603 this.packagingIncludes = packagingIncludes;
604 }
605
606 private static File buildDestinationFile( File buildDir, String uri )
607 {
608 return new File( buildDir, uri );
609 }
610
611
612
613
614
615
616
617
618
619 private static File getEarFile( String basedir, String finalName, String classifier )
620 {
621 if ( classifier == null )
622 {
623 classifier = "";
624 }
625 else if ( classifier.trim().length() > 0 && !classifier.startsWith( "-" ) )
626 {
627 classifier = "-" + classifier;
628 }
629
630 return new File( basedir, finalName + classifier + ".ear" );
631 }
632
633
634
635
636
637
638
639 private String[] getEarFiles( File sourceDir )
640 {
641 DirectoryScanner scanner = new DirectoryScanner();
642 scanner.setBasedir( sourceDir );
643 scanner.setExcludes( getExcludes() );
644 scanner.addDefaultExcludes();
645
646 scanner.setIncludes( getIncludes() );
647
648 scanner.scan();
649
650 return scanner.getIncludedFiles();
651 }
652
653
654
655
656
657
658
659
660
661
662
663 public void unpack( File source, final File destDir, final Collection<String> outdatedResources )
664 throws ArchiverException, NoSuchArchiverException, IOException
665 {
666 UnArchiver unArchiver = archiverManager.getUnArchiver( "zip" );
667 unArchiver.setSourceFile( source );
668 unArchiver.setDestDirectory( destDir );
669 unArchiver.setFileMappers( new FileMapper[] {
670 new FileMapper()
671 {
672 @Override
673 public String getMappedFileName( String pName )
674 {
675 Path destFile = destDir.toPath().resolve( pName );
676 outdatedResources.remove( getWorkDirectory().toPath().relativize( destFile ).toString() );
677 return pName;
678 }
679 }
680 } );
681
682
683 unArchiver.extract();
684 }
685
686 private void copyFile( File source, File target )
687 throws MavenFilteringException, IOException, MojoExecutionException
688 {
689 if ( filtering && !isNonFilteredExtension( source.getName() ) )
690 {
691
692 File parentDirectory = target.getParentFile();
693 if ( parentDirectory != null && !parentDirectory.exists() )
694 {
695 Files.createDirectories( parentDirectory.toPath() );
696 }
697
698 mavenFileFilter.copyFile( source, target, true, getFilterWrappers(), encoding );
699 }
700 else
701 {
702 FileUtils.copyFile( source, target );
703 }
704 }
705
706
707
708
709
710 public boolean isNonFilteredExtension( String fileName )
711 {
712 return !mavenResourcesFiltering.filteredFileExtension( fileName, nonFilteredFileExtensions );
713 }
714
715 private List<FileUtils.FilterWrapper> getFilterWrappers()
716 throws MojoExecutionException
717 {
718 if ( filterWrappers == null )
719 {
720 try
721 {
722 MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
723 mavenResourcesExecution.setMavenProject( getProject() );
724 mavenResourcesExecution.setEscapedBackslashesInFilePath( escapedBackslashesInFilePath );
725 mavenResourcesExecution.setFilters( filters );
726 mavenResourcesExecution.setEscapeString( escapeString );
727
728 filterWrappers = mavenFileFilter.getDefaultFilterWrappers( mavenResourcesExecution );
729 }
730 catch ( MavenFilteringException e )
731 {
732 getLog().error( "Fail to build filtering wrappers " + e.getMessage() );
733 throw new MojoExecutionException( e.getMessage(), e );
734 }
735 }
736 return filterWrappers;
737 }
738
739 private void changeManifestClasspath( EarModule module, File original, JavaEEVersion javaEEVersion )
740 throws MojoFailureException
741 {
742 try
743 {
744 File workDirectory;
745
746
747 if ( original.isFile() )
748 {
749
750
751 workDirectory = new File( new File( getTempFolder(), "temp" ), module.getUri() );
752 if ( workDirectory.mkdirs() )
753 {
754 getLog().debug( "Created a temporary work directory: " + workDirectory.getAbsolutePath() );
755
756
757 zipUnArchiver.setSourceFile( original );
758 zipUnArchiver.setDestDirectory( workDirectory );
759 zipUnArchiver.extract();
760 }
761 else
762 {
763 throw new MojoFailureException( "Failed to create directory " + workDirectory );
764 }
765 }
766 else
767 {
768 workDirectory = original;
769 }
770
771
772 File metaInfDirectory = new File( workDirectory, "META-INF" );
773 boolean newMetaInfCreated = metaInfDirectory.mkdirs();
774 if ( newMetaInfCreated )
775 {
776 getLog().debug(
777 "This project did not have a META-INF directory before, so a new directory was created." );
778 }
779 File manifestFile = new File( metaInfDirectory, "MANIFEST.MF" );
780 boolean newManifestCreated = manifestFile.createNewFile();
781 if ( newManifestCreated )
782 {
783 getLog().debug(
784 "This project did not have a META-INF/MANIFEST.MF file before, so a new file was created." );
785 }
786
787 Manifest mf = readManifest( manifestFile );
788 Attribute classPath = mf.getMainSection().getAttribute( "Class-Path" );
789 List<String> classPathElements = new ArrayList<String>();
790
791 if ( classPath != null )
792 {
793 classPathElements.addAll( Arrays.asList( classPath.getValue().split( " " ) ) );
794 }
795 else
796 {
797 classPath = new Attribute( "Class-Path", "" );
798 }
799
800
801 for ( JarModule jm : getAllJarModules() )
802 {
803 if ( module.getLibDir() != null )
804 {
805
806
807
808
809 File artifact = new File( new File( workDirectory, module.getLibDir() ),
810 module.getArtifact().getFile().getName() );
811
812
813
814
815
816 if ( !artifact.exists() )
817 {
818 getLog().debug( "module does not exist with original file name." );
819 artifact = new File( new File( workDirectory, module.getLibDir() ), jm.getBundleFileName() );
820 getLog().debug( "Artifact with mapping:" + artifact.getAbsolutePath() );
821 }
822
823 if ( !artifact.exists() )
824 {
825 getLog().debug( "Artifact with mapping does not exist." );
826 artifact = new File( new File( workDirectory, module.getLibDir() ),
827 jm.getArtifact().getFile().getName() );
828 getLog().debug( "Artifact with orignal file name:" + artifact.getAbsolutePath() );
829 }
830
831 if ( artifact.exists() )
832 {
833 getLog().debug( " -> Artifact to delete: " + artifact );
834 if ( !artifact.delete() )
835 {
836 getLog().error( "Could not delete '" + artifact + "'" );
837 }
838 }
839 }
840 }
841
842
843 for ( EarModule o : getModules() )
844 {
845 if ( o instanceof JarModule )
846 {
847 JarModule jm = (JarModule) o;
848 if ( classPathElements.contains( jm.getBundleFileName() ) )
849 {
850 classPathElements.set( classPathElements.indexOf( jm.getBundleFileName() ), jm.getUri() );
851 }
852 else
853 {
854 if ( !skipClassPathModification )
855 {
856 classPathElements.add( jm.getUri() );
857 }
858 else
859 {
860 if ( javaEEVersion.lt( JavaEEVersion.FIVE ) || defaultLibBundleDir == null )
861 {
862 classPathElements.add( jm.getUri() );
863 }
864 }
865 }
866 }
867 }
868 classPath.setValue( StringUtils.join( classPathElements.iterator(), " " ) );
869 mf.getMainSection().addConfiguredAttribute( classPath );
870
871
872 try ( FileOutputStream out = new FileOutputStream( manifestFile );
873 OutputStreamWriter writer = new OutputStreamWriter( out, StandardCharsets.UTF_8 ) )
874 {
875 mf.write( writer );
876 }
877
878 if ( original.isFile() )
879 {
880
881 if ( !original.delete() )
882 {
883 getLog().error( "Could not delete original artifact file " + original );
884 }
885
886 getLog().debug( "Zipping module" );
887 zipArchiver.setDestFile( original );
888 zipArchiver.addDirectory( workDirectory );
889 zipArchiver.createArchive();
890 }
891 }
892 catch ( ManifestException | IOException | ArchiverException e )
893 {
894 throw new MojoFailureException( e.getMessage(), e );
895 }
896 }
897
898 private static Manifest readManifest( File manifestFile )
899 throws IOException
900 {
901
902 try ( FileInputStream in = new FileInputStream( manifestFile ) )
903 {
904 Manifest manifest = new Manifest( in );
905 return manifest;
906 }
907 }
908
909 private Collection<String> initOutdatedResources()
910 {
911 final Collection<String> outdatedResources = new ArrayList<>();
912
913 if ( getWorkDirectory().exists() )
914 {
915 try
916 {
917 Files.walkFileTree( getWorkDirectory().toPath(), new SimpleFileVisitor<Path>()
918 {
919 @Override
920 public FileVisitResult visitFile( Path file, BasicFileAttributes attrs )
921 throws IOException
922 {
923 outdatedResources.add( getWorkDirectory().toPath().relativize( file ).toString() );
924 return super.visitFile( file, attrs );
925 }
926 } );
927 }
928 catch ( IOException e )
929 {
930 getLog().warn( "Can't detect outdated resources", e );
931 }
932 }
933 return outdatedResources;
934 }
935
936 private void deleteOutdatedResources( final Collection<String> outdatedResources )
937 {
938 final long startTime = session.getStartTime().getTime();
939
940 for ( String outdatedResource : outdatedResources )
941 {
942 if ( new File( getWorkDirectory(), outdatedResource ).lastModified() < startTime )
943 {
944 getLog().info( "deleting outdated resource " + outdatedResource );
945 new File( getWorkDirectory(), outdatedResource ).delete();
946 }
947 }
948 }
949 }