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.project.MavenProject;
27 import org.apache.maven.shared.filtering.MavenFilteringException;
28 import org.apache.maven.shared.filtering.MavenResourcesExecution;
29 import org.apache.maven.shared.filtering.MavenResourcesFiltering;
30 import org.codehaus.plexus.util.ReaderFactory;
31 import org.codehaus.plexus.util.StringUtils;
32
33 import java.io.File;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.Iterator;
38 import java.util.LinkedHashSet;
39 import java.util.List;
40
41 /**
42 * Copy resources for the main source code to the main output directory.
43 *
44 * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
45 * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
46 * @author Andreas Hoheneder
47 * @author William Ferguson
48 * @version $Id: ResourcesMojo.java 943020 2010-05-11 06:53:57Z krosenvold $
49 * @goal resources
50 * @phase process-resources
51 * @threadSafe
52 *
53 */
54 public class ResourcesMojo
55 extends AbstractMojo
56 {
57
58 /**
59 * The character encoding scheme to be applied when filtering resources.
60 *
61 * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
62 */
63 protected String encoding;
64
65 /**
66 * The output directory into which to copy the resources.
67 *
68 * @parameter default-value="${project.build.outputDirectory}"
69 * @required
70 */
71 private File outputDirectory;
72
73 /**
74 * The list of resources we want to transfer.
75 *
76 * @parameter default-value="${project.resources}"
77 * @required
78 * @readonly
79 */
80 private List resources;
81
82 /**
83 * @parameter default-value="${project}"
84 * @required
85 * @readonly
86 */
87 protected MavenProject project;
88
89 /**
90 * The list of additional filter properties files to be used along with System and project
91 * properties, which would be used for the filtering.
92 * <br/>
93 * See also: {@link ResourcesMojo#filters}.
94 *
95 * @parameter default-value="${project.build.filters}"
96 * @readonly
97 * @since 2.4
98 */
99 protected List 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 */
115 protected List filters;
116
117 /**
118 * If false, don't use the filters specified in the build/filters section of the POM when
119 * processing resources in this mojo execution.
120 * <br/>
121 * See also: {@link ResourcesMojo#buildFilters} and {@link ResourcesMojo#filters}
122 * @parameter default-value="true"
123 * @since 2.4
124 */
125 protected boolean useBuildFilters;
126
127 /**
128 *
129 * @component role="org.apache.maven.shared.filtering.MavenResourcesFiltering" role-hint="default"
130 * @required
131 */
132 protected MavenResourcesFiltering mavenResourcesFiltering;
133
134 /**
135 * @parameter default-value="${session}"
136 * @readonly
137 * @required
138 */
139 protected MavenSession session;
140
141 /**
142 * Expression preceded with the String won't be interpolated
143 * \${foo} will be replaced with ${foo}
144 * @parameter default-value="${maven.resources.escapeString}"
145 * @since 2.3
146 */
147 protected String escapeString;
148
149 /**
150 * Overwrite existing files even if the destination files are newer.
151 * @parameter expression="${maven.resources.overwrite}" default-value="false"
152 * @since 2.3
153 */
154 private boolean overwrite;
155
156 /**
157 * Copy any empty directories included in the Ressources.
158 * @parameter expression="${maven.resources.includeEmptyDirs}" default-value="false"
159 * @since 2.3
160 */
161 protected boolean includeEmptyDirs;
162
163 /**
164 * Additionnal file extensions to not apply filtering (already defined are : jpg, jpeg, gif, bmp, png)
165 * @parameter
166 * @since 2.3
167 */
168 protected List nonFilteredFileExtensions;
169
170 /**
171 * Whether to escape backslashes and colons in windows-style paths.
172 * @parameter expression="${maven.resources.escapeWindowsPaths}" default-value="true"
173 * @since 2.4
174 */
175 protected boolean escapeWindowsPaths;
176
177 /**
178 * <p>
179 * Set of delimiters for expressions to filter within the resources. These delimiters are specified in the
180 * form 'beginToken*endToken'. If no '*' is given, the delimiter is assumed to be the same for start and end.
181 * </p><p>
182 * So, the default filtering delimiters might be specified as:
183 * </p>
184 * <pre>
185 * <delimiters>
186 * <delimiter>${*}</delimiter>
187 * <delimiter>@</delimiter>
188 * </delimiters>
189 * </pre>
190 * <p>
191 * Since the '@' delimiter is the same on both ends, we don't need to specify '@*@' (though we can).
192 * </p>
193 * @parameter
194 * @since 2.4
195 */
196 protected List delimiters;
197
198 /**
199 * @parameter default-value="true"
200 * @since 2.4
201 */
202 protected boolean useDefaultDelimiters;
203
204 public void execute()
205 throws MojoExecutionException
206 {
207 try
208 {
209
210 if ( StringUtils.isEmpty( encoding ) && isFilteringEnabled( getResources() ) )
211 {
212 getLog().warn(
213 "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
214 + ", i.e. build is platform dependent!" );
215 }
216
217 List filters = getCombinedFiltersList();
218
219 MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution( getResources(),
220 getOutputDirectory(),
221 project, encoding, filters,
222 Collections.EMPTY_LIST,
223 session );
224
225 mavenResourcesExecution.setEscapeWindowsPaths( escapeWindowsPaths );
226
227 // never include project build filters in this call, since we've already accounted for the POM build filters
228 // above, in getCombinedFiltersList().
229 mavenResourcesExecution.setInjectProjectBuildFilters( false );
230
231 mavenResourcesExecution.setEscapeString( escapeString );
232 mavenResourcesExecution.setOverwrite( overwrite );
233 mavenResourcesExecution.setIncludeEmptyDirs( includeEmptyDirs );
234
235 // if these are NOT set, just use the defaults, which are '${*}' and '@'.
236 if ( delimiters != null && !delimiters.isEmpty() )
237 {
238 LinkedHashSet delims = new LinkedHashSet();
239 if ( useDefaultDelimiters )
240 {
241 delims.addAll( mavenResourcesExecution.getDelimiters() );
242 }
243
244 for ( Iterator dIt = delimiters.iterator(); dIt.hasNext(); )
245 {
246 String delim = (String) dIt.next();
247 if ( delim == null )
248 {
249 // FIXME: ${filter:*} could also trigger this condition. Need a better long-term solution.
250 delims.add( "${*}" );
251 }
252 else
253 {
254 delims.add( delim );
255 }
256 }
257
258 mavenResourcesExecution.setDelimiters( delims );
259 }
260
261 if ( nonFilteredFileExtensions != null )
262 {
263 mavenResourcesExecution.setNonFilteredFileExtensions( nonFilteredFileExtensions );
264 }
265 mavenResourcesFiltering.filterResources( mavenResourcesExecution );
266 }
267 catch ( MavenFilteringException e )
268 {
269 throw new MojoExecutionException( e.getMessage(), e );
270 }
271 }
272
273 protected List getCombinedFiltersList()
274 {
275 if ( filters == null || filters.isEmpty() )
276 {
277 return useBuildFilters ? buildFilters : null;
278 }
279 else
280 {
281 List result = new ArrayList();
282
283 if ( useBuildFilters && buildFilters != null && !buildFilters.isEmpty() )
284 {
285 result.addAll( buildFilters );
286 }
287
288 result.addAll( filters );
289
290 return result;
291 }
292 }
293
294 /**
295 * Determines whether filtering has been enabled for any resource.
296 *
297 * @param resources The set of resources to check for filtering, may be <code>null</code>.
298 * @return <code>true</code> if at least one resource uses filtering, <code>false</code> otherwise.
299 */
300 private boolean isFilteringEnabled( Collection resources )
301 {
302 if ( resources != null )
303 {
304 for ( Iterator i = resources.iterator(); i.hasNext(); )
305 {
306 Resource resource = (Resource) i.next();
307 if ( resource.isFiltering() )
308 {
309 return true;
310 }
311 }
312 }
313 return false;
314 }
315
316 public List getResources()
317 {
318 return resources;
319 }
320
321 public void setResources( List resources )
322 {
323 this.resources = resources;
324 }
325
326 public File getOutputDirectory()
327 {
328 return outputDirectory;
329 }
330
331 public void setOutputDirectory( File outputDirectory )
332 {
333 this.outputDirectory = outputDirectory;
334 }
335
336 public boolean isOverwrite()
337 {
338 return overwrite;
339 }
340
341 public void setOverwrite( boolean overwrite )
342 {
343 this.overwrite = overwrite;
344 }
345
346 public boolean isIncludeEmptyDirs()
347 {
348 return includeEmptyDirs;
349 }
350
351 public void setIncludeEmptyDirs( boolean includeEmptyDirs )
352 {
353 this.includeEmptyDirs = includeEmptyDirs;
354 }
355
356 public List getFilters()
357 {
358 return filters;
359 }
360
361 public void setFilters( List filters )
362 {
363 this.filters = filters;
364 }
365
366 public List getDelimiters()
367 {
368 return delimiters;
369 }
370
371 public void setDelimiters( List delimiters )
372 {
373 this.delimiters = delimiters;
374 }
375
376 public boolean isUseDefaultDelimiters()
377 {
378 return useDefaultDelimiters;
379 }
380
381 public void setUseDefaultDelimiters( boolean useDefaultDelimiters )
382 {
383 this.useDefaultDelimiters = useDefaultDelimiters;
384 }
385
386 }