View Javadoc

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