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.io.Reader;
25  import java.util.ArrayList;
26  import java.util.Collections;
27  import java.util.Iterator;
28  import java.util.LinkedHashSet;
29  import java.util.List;
30  import java.util.Properties;
31  
32  import org.apache.maven.execution.MavenSession;
33  import org.apache.maven.project.MavenProject;
34  import org.apache.maven.settings.Settings;
35  import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
36  import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
37  import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
38  import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
39  import org.codehaus.plexus.interpolation.RecursionInterceptor;
40  import org.codehaus.plexus.interpolation.SimpleRecursionInterceptor;
41  import org.codehaus.plexus.interpolation.SingleResponseValueSource;
42  import org.codehaus.plexus.interpolation.ValueSource;
43  import org.codehaus.plexus.interpolation.multi.MultiDelimiterStringSearchInterpolator;
44  import org.codehaus.plexus.logging.AbstractLogEnabled;
45  import org.codehaus.plexus.util.FileUtils;
46  import org.codehaus.plexus.util.StringUtils;
47  import org.sonatype.plexus.build.incremental.BuildContext;
48  
49  /**
50   * @author <a href="mailto:olamy@apache.org">olamy</a>
51   * @version $Id: DefaultMavenFileFilter.java 1067324 2011-02-04 22:56:23Z dennisl $
52   *
53   * @plexus.component role="org.apache.maven.shared.filtering.MavenFileFilter"
54   *                   role-hint="default"
55   */
56  public class DefaultMavenFileFilter
57      extends AbstractLogEnabled
58      implements MavenFileFilter
59  {
60  
61      /** @plexus.requirement */
62      private BuildContext buildContext;
63  
64      public void copyFile( File from, File to, boolean filtering, MavenProject mavenProject, List filters,
65                            boolean escapedBackslashesInFilePath, String encoding, MavenSession mavenSession )
66          throws MavenFilteringException
67      {
68          MavenResourcesExecution mre = new MavenResourcesExecution();
69          mre.setMavenProject( mavenProject );
70          mre.setFileFilters( filters );
71          mre.setEscapeWindowsPaths( escapedBackslashesInFilePath );
72          mre.setMavenSession( mavenSession );
73          mre.setInjectProjectBuildFilters( true );
74          
75          List filterWrappers = getDefaultFilterWrappers( mre );
76          copyFile( from, to, filtering, filterWrappers, encoding );
77      }
78      
79      
80      public void copyFile( MavenFileFilterRequest mavenFileFilterRequest )
81          throws MavenFilteringException
82      {
83          List filterWrappers =
84              getDefaultFilterWrappers( mavenFileFilterRequest );
85          
86          copyFile( mavenFileFilterRequest.getFrom(), mavenFileFilterRequest.getTo(),
87                    mavenFileFilterRequest.isFiltering(), filterWrappers, mavenFileFilterRequest.getEncoding() );
88      }
89  
90  
91  
92      public void copyFile( File from, File to, boolean filtering, List filterWrappers, String encoding )
93          throws MavenFilteringException
94      {
95          // overwrite forced to false to preserve backward comp
96          copyFile( from, to, filtering, filterWrappers, encoding, false );
97      }
98  
99      
100     
101     public void copyFile( File from, File to, boolean filtering, List filterWrappers, String encoding,
102                           boolean overwrite )
103         throws MavenFilteringException
104     {
105         try
106         {
107             if ( filtering )
108             {
109                 if ( getLogger().isDebugEnabled() )
110                 {
111                     getLogger().debug( "filtering " + from.getPath() + " to " + to.getPath() );
112                 }
113                 FileUtils.FilterWrapper[] wrappers = (FileUtils.FilterWrapper[]) filterWrappers
114                     .toArray( new FileUtils.FilterWrapper[filterWrappers.size()] );
115                 FileUtils.copyFile( from, to, encoding, wrappers );
116             }
117             else
118             {
119                 if ( getLogger().isDebugEnabled() )
120                 {
121                     getLogger().debug( "copy " + from.getPath() + " to " + to.getPath() );
122                 }
123                 FileUtils.copyFile( from, to, encoding, new FileUtils.FilterWrapper[0], overwrite );
124             }
125 
126             buildContext.refresh( to );
127         }
128         catch ( IOException e )
129         {
130             throw new MavenFilteringException( e.getMessage(), e );
131         }
132         
133     }
134 
135     /** 
136      * @see org.apache.maven.shared.filtering.MavenFileFilter#getDefaultFilterWrappers(org.apache.maven.project.MavenProject, java.util.List, boolean, org.apache.maven.execution.MavenSession)
137      * @deprecated
138      */
139     public List getDefaultFilterWrappers( final MavenProject mavenProject, List filters,
140                                           final boolean escapedBackslashesInFilePath, MavenSession mavenSession )
141         throws MavenFilteringException
142     {
143         return getDefaultFilterWrappers( mavenProject, filters, escapedBackslashesInFilePath, mavenSession, null );
144     }
145 
146     
147     
148     
149     public List getDefaultFilterWrappers( final MavenProject mavenProject, List filters,
150                                           final boolean escapedBackslashesInFilePath, MavenSession mavenSession,
151                                           MavenResourcesExecution mavenResourcesExecution )
152         throws MavenFilteringException
153     {
154 
155         MavenResourcesExecution mre = mavenResourcesExecution == null ? new MavenResourcesExecution()
156                         : mavenResourcesExecution.copyOf();
157         
158         mre.setMavenProject( mavenProject );
159         mre.setMavenSession( mavenSession );
160         mre.setFilters( filters );
161         mre.setEscapedBackslashesInFilePath( escapedBackslashesInFilePath );
162         
163         return getDefaultFilterWrappers( mre );
164 
165     }
166     
167     public List getDefaultFilterWrappers( final AbstractMavenFilteringRequest req )
168         throws MavenFilteringException
169     {
170         // backup values
171         boolean supportMultiLineFiltering = req.isSupportMultiLineFiltering();
172         
173         // compensate for null parameter value.
174         final AbstractMavenFilteringRequest request = req == null ? new MavenFileFilterRequest() : req;
175 
176         request.setSupportMultiLineFiltering( supportMultiLineFiltering );
177         
178         // Here we build some properties which will be used to read some properties files
179         // to interpolate the expression ${ } in this properties file
180 
181         // Take a copy of filterProperties to ensure that evaluated filterTokens are not propagated
182         // to subsequent filter files. Note: this replicates current behaviour and seems to make sense.
183 
184         final Properties baseProps = new Properties();
185 
186         // Project properties
187         if ( request.getMavenProject() != null )
188         {
189             baseProps.putAll( request.getMavenProject().getProperties() == null ? Collections.EMPTY_MAP
190                             : request.getMavenProject().getProperties() );
191         }
192         // TODO this is NPE free but do we consider this as normal
193         // or do we have to throw an MavenFilteringException with mavenSession cannot be null
194         if ( request.getMavenSession() != null )
195         {
196             // execution properties wins
197             baseProps.putAll( request.getMavenSession().getExecutionProperties() );
198         }
199 
200         // now we build properties to use for resources interpolation
201 
202         final Properties filterProperties = new Properties();
203 
204         loadProperties( filterProperties, request.getFileFilters(), baseProps );
205         if ( filterProperties.size() < 1 )
206         {
207             filterProperties.putAll( baseProps );
208         }
209 
210         if ( request.getMavenProject() != null )
211         {
212             if ( request.isInjectProjectBuildFilters() )
213             {
214                 List buildFilters = request.getMavenProject().getBuild().getFilters();
215                 buildFilters.removeAll( request.getFileFilters() );
216                 
217                 loadProperties( filterProperties, buildFilters, baseProps );
218             }
219 
220             // Project properties
221             filterProperties.putAll( request.getMavenProject().getProperties() == null ? Collections.EMPTY_MAP
222                             : request.getMavenProject().getProperties() );
223         }
224         if ( request.getMavenSession() != null )
225         {
226             // execution properties wins
227             filterProperties.putAll( request.getMavenSession().getExecutionProperties() );
228         }
229 
230         if ( request.getAdditionalProperties() != null )
231         {
232             // additional properties wins
233             filterProperties.putAll( request.getAdditionalProperties() );
234         }
235         
236         List defaultFilterWrappers
237             = request == null ? new ArrayList( 1 ) : new ArrayList( request.getDelimiters().size() + 1 );
238 
239         if ( getLogger().isDebugEnabled() )
240         {
241             getLogger().debug( "properties used " + filterProperties );
242         }
243 
244         final ValueSource propertiesValueSource = new PropertiesBasedValueSource( filterProperties );
245 
246         if ( request != null )
247         {
248             FileUtils.FilterWrapper wrapper = new Wrapper( request.getDelimiters(), request.getMavenProject(),
249                                                            request.getMavenSession(), propertiesValueSource,
250                                                            request.getProjectStartExpressions(),
251                                                            request.getEscapeString(), request.isEscapeWindowsPaths(),
252                                                            request.isSupportMultiLineFiltering() );
253             
254             defaultFilterWrappers.add( wrapper );
255         }
256 
257         return defaultFilterWrappers;
258     }    
259 
260     /**
261      * protected only for testing reason !
262      */
263     protected void loadProperties( Properties filterProperties, List /* String */propertiesFilePaths,
264                                  Properties baseProps )
265         throws MavenFilteringException
266     {
267         if ( propertiesFilePaths != null )
268         {
269             Properties workProperties = new Properties();
270             workProperties.putAll( baseProps );
271 
272             for ( Iterator iterator = propertiesFilePaths.iterator(); iterator.hasNext(); )
273             {
274                 String filterFile = (String) iterator.next();
275                 if ( StringUtils.isEmpty( filterFile ) )
276                 {
277                     // skip empty file name
278                     continue;
279                 }
280                 try
281                 {
282                     // TODO new File should be new File(mavenProject.getBasedir(), filterfile ) ?
283                     Properties properties = PropertyUtils.loadPropertyFile( new File( filterFile ), workProperties );
284                     filterProperties.putAll( properties );
285                     workProperties.putAll( properties );
286                 }
287                 catch ( IOException e )
288                 {
289                     throw new MavenFilteringException( "Error loading property file '" + filterFile + "'", e );
290                 }
291             }
292         }
293     }
294     
295     private static final class Wrapper extends FileUtils.FilterWrapper
296     {
297         
298         private LinkedHashSet delimiters;
299         
300         private MavenProject project;
301         
302         private ValueSource propertiesValueSource;
303         
304         private List projectStartExpressions;
305         
306         private String escapeString;
307         
308         private boolean escapeWindowsPaths;
309 
310         private final MavenSession mavenSession;
311         
312         private boolean supportMultiLineFiltering;
313 
314         Wrapper( LinkedHashSet delimiters, MavenProject project, MavenSession mavenSession,
315                  ValueSource propertiesValueSource, List projectStartExpressions, String escapeString,
316                  boolean escapeWindowsPaths, boolean supportMultiLineFiltering )
317         {
318             super();
319             this.delimiters = delimiters;
320             this.project = project;
321             this.mavenSession = mavenSession;
322             this.propertiesValueSource = propertiesValueSource;
323             this.projectStartExpressions = projectStartExpressions;
324             this.escapeString = escapeString;
325             this.escapeWindowsPaths = escapeWindowsPaths;
326             this.supportMultiLineFiltering = supportMultiLineFiltering;
327         }
328 
329         public Reader getReader( Reader reader )
330         {
331             MultiDelimiterStringSearchInterpolator interpolator = new MultiDelimiterStringSearchInterpolator();
332             interpolator.setDelimiterSpecs( delimiters );
333             
334             RecursionInterceptor ri = null;
335             if ( projectStartExpressions != null && !projectStartExpressions.isEmpty() )
336             {
337                 ri = new PrefixAwareRecursionInterceptor( projectStartExpressions, true );
338             }
339             else
340             {
341                 ri = new SimpleRecursionInterceptor();
342             }
343             
344             interpolator.addValueSource( propertiesValueSource );
345             
346             if ( project != null )
347             {
348                 interpolator.addValueSource( new PrefixedObjectValueSource( projectStartExpressions, project, true ) );
349             }
350             
351             if ( mavenSession != null )
352             {
353                 interpolator.addValueSource( new PrefixedObjectValueSource( "session", mavenSession ) );
354                 
355                 final Settings settings = mavenSession.getSettings();
356                 if ( settings != null )
357                 {
358                     interpolator.addValueSource( new PrefixedObjectValueSource( "settings", settings ) );
359                     interpolator.addValueSource( new SingleResponseValueSource( "localRepository",
360                                                                                 settings.getLocalRepository() ) );
361                 }
362             }
363             
364             interpolator.setEscapeString( escapeString );
365             
366             if ( escapeWindowsPaths )
367             {
368                 interpolator.addPostProcessor( new InterpolationPostProcessor()
369                 {
370                     public Object execute( String expression, Object value )
371                     {
372                         if ( value instanceof String )
373                         {
374                             return FilteringUtils.escapeWindowsPath( (String) value );
375                         }
376                         
377                         return value;
378                     }
379                 } );
380             }
381             
382             MultiDelimiterInterpolatorFilterReaderLineEnding filterReader = 
383                 new MultiDelimiterInterpolatorFilterReaderLineEnding( reader, interpolator, supportMultiLineFiltering );
384             filterReader.setRecursionInterceptor( ri );
385             filterReader.setDelimiterSpecs( delimiters );
386             
387             filterReader.setInterpolateWithPrefixPattern( false );
388             filterReader.setEscapeString( escapeString );
389             
390             return filterReader;
391         }
392         
393     }
394 
395 }