View Javadoc

1   package org.apache.maven.plugin.resources;
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 org.apache.maven.execution.MavenSession;
23  import org.apache.maven.model.Resource;
24  import org.apache.maven.plugin.AbstractMojo;
25  import org.apache.maven.plugin.MojoExecutionException;
26  import org.apache.maven.plugins.annotations.Component;
27  import org.apache.maven.plugins.annotations.LifecyclePhase;
28  import org.apache.maven.plugins.annotations.Mojo;
29  import org.apache.maven.plugins.annotations.Parameter;
30  import org.apache.maven.project.MavenProject;
31  import org.apache.maven.shared.filtering.MavenFilteringException;
32  import org.apache.maven.shared.filtering.MavenResourcesExecution;
33  import org.apache.maven.shared.filtering.MavenResourcesFiltering;
34  import org.codehaus.plexus.PlexusConstants;
35  import org.codehaus.plexus.PlexusContainer;
36  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
37  import org.codehaus.plexus.context.Context;
38  import org.codehaus.plexus.context.ContextException;
39  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
40  import org.codehaus.plexus.util.ReaderFactory;
41  import org.codehaus.plexus.util.StringUtils;
42  
43  import java.io.File;
44  import java.util.ArrayList;
45  import java.util.Collection;
46  import java.util.Collections;
47  import java.util.Iterator;
48  import java.util.LinkedHashSet;
49  import java.util.List;
50  
51  /**
52   * Copy resources for the main source code to the main output directory.
53   * Always uses the project.build.resources element to specify the resources to copy.
54   *
55   * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
56   * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
57   * @author Andreas Hoheneder
58   * @author William Ferguson
59   */
60  @Mojo( name = "resources", defaultPhase = LifecyclePhase.PROCESS_RESOURCES, threadSafe = true )
61  public class ResourcesMojo
62      extends AbstractMojo
63      implements Contextualizable
64  {
65  
66      /**
67       * The character encoding scheme to be applied when filtering resources.
68       */
69      @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
70      protected String encoding;
71  
72      /**
73       * The output directory into which to copy the resources.
74       */
75      @Parameter( defaultValue = "${project.build.outputDirectory}", required = true )
76      private File outputDirectory;
77  
78      /**
79       * The list of resources we want to transfer.
80       */
81      @Parameter( defaultValue = "${project.resources}", required = true, readonly = true )
82      private List<Resource> resources;
83  
84      /**
85       *
86       */
87      @Parameter( defaultValue = "${project}", required = true, readonly = true )
88      protected MavenProject project;
89  
90      /**
91       * The list of additional filter properties files to be used along with System and project
92       * properties, which would be used for the filtering.
93       * <br/>
94       * See also: {@link ResourcesMojo#filters}.
95       *
96       * @since 2.4
97       */
98      @Parameter( defaultValue = "${project.build.filters}", readonly = true )
99      protected List<String> buildFilters;
100 
101     /**
102      * The list of extra filter properties files to be used along with System properties,
103      * project properties, and filter properties files specified in the POM build/filters section,
104      * which should be used for the filtering during the current mojo execution.
105      * <br/>
106      * Normally, these will be configured from a plugin's execution section, to provide a different
107      * set of filters for a particular execution. For instance, starting in Maven 2.2.0, you have the
108      * option of configuring executions with the id's <code>default-resources</code> and
109      * <code>default-testResources</code> to supply different configurations for the two
110      * different types of resources. By supplying <code>extraFilters</code> configurations, you
111      * can separate which filters are used for which type of resource.
112      */
113     @Parameter
114     protected List<String> filters;
115 
116     /**
117      * If false, don't use the filters specified in the build/filters section of the POM when
118      * processing resources in this mojo execution.
119      * <br/>
120      * See also: {@link ResourcesMojo#buildFilters} and {@link ResourcesMojo#filters}
121      *
122      * @since 2.4
123      */
124     @Parameter( defaultValue = "true" )
125     protected boolean useBuildFilters;
126 
127     /**
128      *
129      */
130     @Component( role = MavenResourcesFiltering.class, hint = "default" )
131     protected MavenResourcesFiltering mavenResourcesFiltering;
132 
133     /**
134      *
135      */
136     @Parameter( defaultValue = "${session}", required = true, readonly = true )
137     protected MavenSession session;
138 
139     /**
140      * Expression preceded with the String won't be interpolated
141      * \${foo} will be replaced with ${foo}
142      *
143      * @since 2.3
144      */
145     @Parameter( property = "maven.resources.escapeString" )
146     protected String escapeString;
147 
148     /**
149      * Overwrite existing files even if the destination files are newer.
150      *
151      * @since 2.3
152      */
153     @Parameter( property = "maven.resources.overwrite", defaultValue = "false" )
154     private boolean overwrite;
155 
156     /**
157      * Copy any empty directories included in the Resources.
158      *
159      * @since 2.3
160      */
161     @Parameter( property = "maven.resources.includeEmptyDirs", defaultValue = "false" )
162     protected boolean includeEmptyDirs;
163 
164     /**
165      * Additional file extensions to not apply filtering (already defined are : jpg, jpeg, gif, bmp, png)
166      *
167      * @since 2.3
168      */
169     @Parameter
170     protected List<String> nonFilteredFileExtensions;
171 
172     /**
173      * Whether to escape backslashes and colons in windows-style paths.
174      *
175      * @since 2.4
176      */
177     @Parameter( property = "maven.resources.escapeWindowsPaths", defaultValue = "true" )
178     protected boolean escapeWindowsPaths;
179 
180     /**
181      * <p>
182      * Set of delimiters for expressions to filter within the resources. These delimiters are specified in the
183      * form 'beginToken*endToken'. If no '*' is given, the delimiter is assumed to be the same for start and end.
184      * </p><p>
185      * So, the default filtering delimiters might be specified as:
186      * </p>
187      * <pre>
188      * &lt;delimiters&gt;
189      *   &lt;delimiter&gt;${*}&lt;/delimiter&gt;
190      *   &lt;delimiter&gt;@&lt;/delimiter&gt;
191      * &lt;/delimiters&gt;
192      * </pre>
193      * <p>
194      * Since the '@' delimiter is the same on both ends, we don't need to specify '@*@' (though we can).
195      * </p>
196      *
197      * @since 2.4
198      */
199     @Parameter
200     protected List<String> delimiters;
201 
202     /**
203      * @since 2.4
204      */
205     @Parameter( defaultValue = "true" )
206     protected boolean useDefaultDelimiters;
207 
208     /**
209      * <p>
210      * List of plexus components hint which implements {@link MavenResourcesFiltering#filterResources(MavenResourcesExecution)}.
211      * They will be executed after the resources copying/filtering.
212      * </p>
213      *
214      * @since 2.4
215      */
216     @Parameter
217     private List<String> mavenFilteringHints;
218 
219     /**
220      * @since 2.4
221      */
222     private PlexusContainer plexusContainer;
223 
224     /**
225      * @since 2.4
226      */
227     private List<MavenResourcesFiltering> mavenFilteringComponents = new ArrayList<MavenResourcesFiltering>();
228 
229     /**
230      * stop searching endToken at the end of line
231      *
232      * @since 2.5
233      */
234     @Parameter( property = "maven.resources.supportMultiLineFiltering", defaultValue = "false" )
235     private boolean supportMultiLineFiltering;
236 
237     public void contextualize( Context context )
238         throws ContextException
239     {
240         plexusContainer = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
241     }
242 
243     public void execute()
244         throws MojoExecutionException
245     {
246         try
247         {
248 
249             if ( StringUtils.isEmpty( encoding ) && isFilteringEnabled( getResources() ) )
250             {
251                 getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
252                                    + ", i.e. build is platform dependent!" );
253             }
254 
255             List filters = getCombinedFiltersList();
256 
257             MavenResourcesExecution mavenResourcesExecution =
258                 new MavenResourcesExecution( getResources(), getOutputDirectory(), project, encoding, filters,
259                                              Collections.<String>emptyList(), session );
260 
261             mavenResourcesExecution.setEscapeWindowsPaths( escapeWindowsPaths );
262 
263             // never include project build filters in this call, since we've already accounted for the POM build filters
264             // above, in getCombinedFiltersList().
265             mavenResourcesExecution.setInjectProjectBuildFilters( false );
266 
267             mavenResourcesExecution.setEscapeString( escapeString );
268             mavenResourcesExecution.setOverwrite( overwrite );
269             mavenResourcesExecution.setIncludeEmptyDirs( includeEmptyDirs );
270             mavenResourcesExecution.setSupportMultiLineFiltering( supportMultiLineFiltering );
271 
272             // if these are NOT set, just use the defaults, which are '${*}' and '@'.
273             if ( delimiters != null && !delimiters.isEmpty() )
274             {
275                 LinkedHashSet<String> delims = new LinkedHashSet<String>();
276                 if ( useDefaultDelimiters )
277                 {
278                     delims.addAll( mavenResourcesExecution.getDelimiters() );
279                 }
280 
281                 for ( String delim : delimiters )
282                 {
283                     if ( delim == null )
284                     {
285                         // FIXME: ${filter:*} could also trigger this condition. Need a better long-term solution.
286                         delims.add( "${*}" );
287                     }
288                     else
289                     {
290                         delims.add( delim );
291                     }
292                 }
293 
294                 mavenResourcesExecution.setDelimiters( delims );
295             }
296 
297             if ( nonFilteredFileExtensions != null )
298             {
299                 mavenResourcesExecution.setNonFilteredFileExtensions( nonFilteredFileExtensions );
300             }
301             mavenResourcesFiltering.filterResources( mavenResourcesExecution );
302 
303             executeUserFilterComponents( mavenResourcesExecution );
304         }
305         catch ( MavenFilteringException e )
306         {
307             throw new MojoExecutionException( e.getMessage(), e );
308         }
309     }
310 
311     /**
312      * @since 2.5
313      */
314     protected void executeUserFilterComponents( MavenResourcesExecution mavenResourcesExecution )
315         throws MojoExecutionException, MavenFilteringException
316     {
317 
318         if ( mavenFilteringHints != null )
319         {
320             for ( Iterator ite = mavenFilteringHints.iterator(); ite.hasNext(); )
321             {
322                 String hint = (String) ite.next();
323                 try
324                 {
325                     mavenFilteringComponents.add(
326                         (MavenResourcesFiltering) plexusContainer.lookup( MavenResourcesFiltering.class.getName(),
327                                                                           hint ) );
328                 }
329                 catch ( ComponentLookupException e )
330                 {
331                     throw new MojoExecutionException( e.getMessage(), e );
332                 }
333             }
334         }
335         else
336         {
337             getLog().debug( "no use filter components" );
338         }
339 
340         if ( mavenFilteringComponents != null && !mavenFilteringComponents.isEmpty() )
341         {
342             getLog().debug( "execute user filters" );
343             for ( MavenResourcesFiltering filter : mavenFilteringComponents )
344             {
345                 filter.filterResources( mavenResourcesExecution );
346             }
347         }
348     }
349 
350     protected List<String> getCombinedFiltersList()
351     {
352         if ( filters == null || filters.isEmpty() )
353         {
354             return useBuildFilters ? buildFilters : null;
355         }
356         else
357         {
358             List<String> result = new ArrayList<String>();
359 
360             if ( useBuildFilters && buildFilters != null && !buildFilters.isEmpty() )
361             {
362                 result.addAll( buildFilters );
363             }
364 
365             result.addAll( filters );
366 
367             return result;
368         }
369     }
370 
371     /**
372      * Determines whether filtering has been enabled for any resource.
373      *
374      * @param resources The set of resources to check for filtering, may be <code>null</code>.
375      * @return <code>true</code> if at least one resource uses filtering, <code>false</code> otherwise.
376      */
377     private boolean isFilteringEnabled( Collection<Resource> resources )
378     {
379         if ( resources != null )
380         {
381             for ( Resource resource : resources )
382             {
383                 if ( resource.isFiltering() )
384                 {
385                     return true;
386                 }
387             }
388         }
389         return false;
390     }
391 
392     public List<Resource> getResources()
393     {
394         return resources;
395     }
396 
397     public void setResources( List<Resource> resources )
398     {
399         this.resources = resources;
400     }
401 
402     public File getOutputDirectory()
403     {
404         return outputDirectory;
405     }
406 
407     public void setOutputDirectory( File outputDirectory )
408     {
409         this.outputDirectory = outputDirectory;
410     }
411 
412     public boolean isOverwrite()
413     {
414         return overwrite;
415     }
416 
417     public void setOverwrite( boolean overwrite )
418     {
419         this.overwrite = overwrite;
420     }
421 
422     public boolean isIncludeEmptyDirs()
423     {
424         return includeEmptyDirs;
425     }
426 
427     public void setIncludeEmptyDirs( boolean includeEmptyDirs )
428     {
429         this.includeEmptyDirs = includeEmptyDirs;
430     }
431 
432     public List<String> getFilters()
433     {
434         return filters;
435     }
436 
437     public void setFilters( List<String> filters )
438     {
439         this.filters = filters;
440     }
441 
442     public List<String> getDelimiters()
443     {
444         return delimiters;
445     }
446 
447     public void setDelimiters( List<String> delimiters )
448     {
449         this.delimiters = delimiters;
450     }
451 
452     public boolean isUseDefaultDelimiters()
453     {
454         return useDefaultDelimiters;
455     }
456 
457     public void setUseDefaultDelimiters( boolean useDefaultDelimiters )
458     {
459         this.useDefaultDelimiters = useDefaultDelimiters;
460     }
461 
462 }