1 package org.apache.maven.shared.filtering;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.execution.MavenSession;
23 import org.apache.maven.model.Resource;
24 import org.apache.maven.project.MavenProject;
25 import org.codehaus.plexus.logging.AbstractLogEnabled;
26 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
27 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
28 import org.codehaus.plexus.util.FileUtils;
29 import org.codehaus.plexus.util.PathTool;
30 import org.codehaus.plexus.util.ReaderFactory;
31 import org.codehaus.plexus.util.Scanner;
32 import org.codehaus.plexus.util.StringUtils;
33 import org.sonatype.plexus.build.incremental.BuildContext;
34
35 import java.io.File;
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.List;
40
41
42
43
44
45
46 public class DefaultMavenResourcesFiltering
47 extends AbstractLogEnabled
48 implements MavenResourcesFiltering, Initializable
49 {
50
51 private static final String[] EMPTY_STRING_ARRAY = { };
52
53 private static final String[] DEFAULT_INCLUDES = { "**/**" };
54
55 private List<String> defaultNonFilteredFileExtensions;
56
57
58
59
60 private BuildContext buildContext;
61
62
63
64
65 public void initialize()
66 throws InitializationException
67 {
68
69 this.defaultNonFilteredFileExtensions = new ArrayList<String>( 5 );
70 this.defaultNonFilteredFileExtensions.add( "jpg" );
71 this.defaultNonFilteredFileExtensions.add( "jpeg" );
72 this.defaultNonFilteredFileExtensions.add( "gif" );
73 this.defaultNonFilteredFileExtensions.add( "bmp" );
74 this.defaultNonFilteredFileExtensions.add( "png" );
75 }
76
77
78
79
80
81 private MavenFileFilter mavenFileFilter;
82
83 public void filterResources( List<Resource> resources, File outputDirectory, MavenProject mavenProject,
84 String encoding, List<String> fileFilters, List<String> nonFilteredFileExtensions,
85 MavenSession mavenSession )
86 throws MavenFilteringException
87 {
88 MavenResourcesExecution mavenResourcesExecution =
89 new MavenResourcesExecution( resources, outputDirectory, mavenProject, encoding, fileFilters,
90 nonFilteredFileExtensions, mavenSession );
91 mavenResourcesExecution.setUseDefaultFilterWrappers( true );
92
93
94 filterResources( mavenResourcesExecution );
95 }
96
97 public void filterResources( List<Resource> resources, File outputDirectory, String encoding,
98 List<FileUtils.FilterWrapper> filterWrappers, File resourcesBaseDirectory,
99 List<String> nonFilteredFileExtensions )
100 throws MavenFilteringException
101 {
102 MavenResourcesExecution mavenResourcesExecution =
103 new MavenResourcesExecution( resources, outputDirectory, encoding, filterWrappers, resourcesBaseDirectory,
104 nonFilteredFileExtensions );
105 filterResources( mavenResourcesExecution );
106 }
107
108
109 public boolean filteredFileExtension( String fileName, List<String> userNonFilteredFileExtensions )
110 {
111 List<String> nonFilteredFileExtensions = new ArrayList<String>( getDefaultNonFilteredFileExtensions() );
112 if ( userNonFilteredFileExtensions != null )
113 {
114 nonFilteredFileExtensions.addAll( userNonFilteredFileExtensions );
115 }
116 boolean filteredFileExtension =
117 !nonFilteredFileExtensions.contains( StringUtils.lowerCase( FileUtils.extension( fileName ) ) );
118 if ( getLogger().isDebugEnabled() )
119 {
120 getLogger().debug(
121 "file " + fileName + " has a" + ( filteredFileExtension ? " " : " non " ) + "filtered file extension" );
122 }
123 return filteredFileExtension;
124 }
125
126 public List<String> getDefaultNonFilteredFileExtensions()
127 {
128 if ( this.defaultNonFilteredFileExtensions == null )
129 {
130 this.defaultNonFilteredFileExtensions = new ArrayList<String>();
131 }
132 return this.defaultNonFilteredFileExtensions;
133 }
134
135 public void filterResources( MavenResourcesExecution mavenResourcesExecution )
136 throws MavenFilteringException
137 {
138 if ( mavenResourcesExecution == null )
139 {
140 throw new MavenFilteringException( "mavenResourcesExecution cannot be null" );
141 }
142
143 if ( mavenResourcesExecution.getResources() == null )
144 {
145 getLogger().info( "No resources configured skip copying/filtering" );
146 return;
147 }
148
149 if ( mavenResourcesExecution.getOutputDirectory() == null )
150 {
151 throw new MavenFilteringException( "outputDirectory cannot be null" );
152 }
153
154 if ( mavenResourcesExecution.isUseDefaultFilterWrappers() )
155 {
156 List<FileUtils.FilterWrapper> filterWrappers = new ArrayList<FileUtils.FilterWrapper>();
157 if ( mavenResourcesExecution.getFilterWrappers() != null )
158 {
159 filterWrappers.addAll( mavenResourcesExecution.getFilterWrappers() );
160 }
161 filterWrappers.addAll( mavenFileFilter.getDefaultFilterWrappers( mavenResourcesExecution ) );
162 mavenResourcesExecution.setFilterWrappers( filterWrappers );
163 }
164
165 if ( mavenResourcesExecution.getEncoding() == null || mavenResourcesExecution.getEncoding().length() < 1 )
166 {
167 getLogger().warn( "Using platform encoding (" + ReaderFactory.FILE_ENCODING
168 + " actually) to copy filtered resources, i.e. build is platform dependent!" );
169 }
170 else
171 {
172 getLogger().info(
173 "Using '" + mavenResourcesExecution.getEncoding() + "' encoding to copy filtered resources." );
174 }
175
176 for ( Resource resource : mavenResourcesExecution.getResources() )
177 {
178
179 if ( getLogger().isDebugEnabled() )
180 {
181 String ls = System.getProperty( "line.separator" );
182 StringBuffer debugMessage =
183 new StringBuffer( "resource with targetPath " + resource.getTargetPath() ).append( ls );
184 debugMessage.append( "directory " + resource.getDirectory() ).append( ls );
185 debugMessage.append( "excludes " + ( resource.getExcludes() == null
186 ? " empty "
187 : resource.getExcludes().toString() ) ).append( ls );
188 debugMessage.append(
189 "includes " + ( resource.getIncludes() == null ? " empty " : resource.getIncludes().toString() ) );
190 getLogger().debug( debugMessage.toString() );
191 }
192
193 String targetPath = resource.getTargetPath();
194
195 File resourceDirectory = new File( resource.getDirectory() );
196
197 if ( !resourceDirectory.isAbsolute() )
198 {
199 resourceDirectory =
200 new File( mavenResourcesExecution.getResourcesBaseDirectory(), resourceDirectory.getPath() );
201 }
202
203 if ( !resourceDirectory.exists() )
204 {
205 getLogger().info( "skip non existing resourceDirectory " + resourceDirectory.getPath() );
206 continue;
207 }
208
209
210
211 File outputDirectory = mavenResourcesExecution.getOutputDirectory();
212 boolean outputExists = outputDirectory.exists();
213 if ( !outputExists && !outputDirectory.mkdirs() )
214 {
215 throw new MavenFilteringException( "Cannot create resource output directory: " + outputDirectory );
216 }
217
218 boolean ignoreDelta = !outputExists || buildContext.hasDelta( mavenResourcesExecution.getFileFilters() )
219 || buildContext.hasDelta( getRelativeOutputDirectory( mavenResourcesExecution ) );
220 getLogger().debug( "ignoreDelta " + ignoreDelta );
221 Scanner scanner = buildContext.newScanner( resourceDirectory, ignoreDelta );
222
223 setupScanner( resource, scanner );
224
225 scanner.scan();
226
227 if ( mavenResourcesExecution.isIncludeEmptyDirs() )
228 {
229 try
230 {
231 File targetDirectory =
232 targetPath == null ? outputDirectory : new File( outputDirectory, targetPath );
233 copyDirectoryLayout( resourceDirectory, targetDirectory, scanner );
234 }
235 catch ( IOException e )
236 {
237 throw new MavenFilteringException(
238 "Cannot copy directory structure from " + resourceDirectory.getPath() + " to "
239 + outputDirectory.getPath() );
240 }
241 }
242
243 List<String> includedFiles = Arrays.asList( scanner.getIncludedFiles() );
244
245 getLogger().info(
246 "Copying " + includedFiles.size() + " resource" + ( includedFiles.size() > 1 ? "s" : "" ) + (
247 targetPath == null ? "" : " to " + targetPath ) );
248
249 for ( String name : includedFiles )
250 {
251
252 File source = new File( resourceDirectory, name );
253
254
255
256 File destinationFile = getDestinationFile( outputDirectory, targetPath, name );
257
258 boolean filteredExt =
259 filteredFileExtension( source.getName(), mavenResourcesExecution.getNonFilteredFileExtensions() );
260
261 mavenFileFilter.copyFile( source, destinationFile, resource.isFiltering() && filteredExt,
262 mavenResourcesExecution.getFilterWrappers(),
263 mavenResourcesExecution.getEncoding(),
264 mavenResourcesExecution.isOverwrite() );
265 }
266
267
268
269 scanner = buildContext.newDeleteScanner( resourceDirectory );
270
271 setupScanner( resource, scanner );
272
273 scanner.scan();
274
275 List<String> deletedFiles = Arrays.asList( scanner.getIncludedFiles() );
276
277 for ( String name : deletedFiles )
278 {
279 File destinationFile = getDestinationFile( outputDirectory, targetPath, name );
280
281 destinationFile.delete();
282
283 buildContext.refresh( destinationFile );
284 }
285
286 }
287
288 }
289
290 private File getDestinationFile( File outputDirectory, String targetPath, String name )
291 {
292 String destination = name;
293
294 if ( targetPath != null )
295 {
296 destination = targetPath + "/" + name;
297 }
298
299 File destinationFile = new File( destination );
300 if ( !destinationFile.isAbsolute() )
301 {
302 destinationFile = new File( outputDirectory, destination );
303 }
304
305 if ( !destinationFile.getParentFile().exists() )
306 {
307 destinationFile.getParentFile().mkdirs();
308 }
309 return destinationFile;
310 }
311
312 private String[] setupScanner( Resource resource, Scanner scanner )
313 {
314 String[] includes = null;
315 if ( resource.getIncludes() != null && !resource.getIncludes().isEmpty() )
316 {
317 includes = (String[]) resource.getIncludes().toArray( EMPTY_STRING_ARRAY );
318 }
319 else
320 {
321 includes = DEFAULT_INCLUDES;
322 }
323 scanner.setIncludes( includes );
324
325 String[] excludes = null;
326 if ( resource.getExcludes() != null && !resource.getExcludes().isEmpty() )
327 {
328 excludes = (String[]) resource.getExcludes().toArray( EMPTY_STRING_ARRAY );
329 scanner.setExcludes( excludes );
330 }
331
332 scanner.addDefaultExcludes();
333 return includes;
334 }
335
336 private void copyDirectoryLayout( File sourceDirectory, File destinationDirectory, Scanner scanner )
337 throws IOException
338 {
339 if ( sourceDirectory == null )
340 {
341 throw new IOException( "source directory can't be null." );
342 }
343
344 if ( destinationDirectory == null )
345 {
346 throw new IOException( "destination directory can't be null." );
347 }
348
349 if ( sourceDirectory.equals( destinationDirectory ) )
350 {
351 throw new IOException( "source and destination are the same directory." );
352 }
353
354 if ( !sourceDirectory.exists() )
355 {
356 throw new IOException( "Source directory doesn't exists (" + sourceDirectory.getAbsolutePath() + ")." );
357 }
358
359 List<String> includedDirectories = Arrays.asList( scanner.getIncludedDirectories() );
360
361 for ( String name : includedDirectories )
362 {
363 File source = new File( sourceDirectory, name );
364
365 if ( source.equals( sourceDirectory ) )
366 {
367 continue;
368 }
369
370 File destination = new File( destinationDirectory, name );
371 destination.mkdirs();
372 }
373 }
374
375 private String getRelativeOutputDirectory( MavenResourcesExecution execution )
376 {
377 String relOutDir = execution.getOutputDirectory().getAbsolutePath();
378
379 if ( execution.getMavenProject() != null && execution.getMavenProject().getBasedir() != null )
380 {
381 String basedir = execution.getMavenProject().getBasedir().getAbsolutePath();
382 relOutDir = PathTool.getRelativeFilePath( basedir, relOutDir );
383 if ( relOutDir == null )
384 {
385 relOutDir = execution.getOutputDirectory().getPath();
386 }
387 else
388 {
389 relOutDir = relOutDir.replace( '\\', '/' );
390 }
391 }
392
393 return relOutDir;
394 }
395
396 }