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