1 package org.apache.maven.plugin.dependency;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
5 * agreements. See the NOTICE file distributed with this work for additional information regarding
6 * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance with the License. You may obtain a
8 * copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software distributed under the License
13 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14 * or implied. See the License for the specific language governing permissions and limitations under
15 * the License.
16 */
17
18 import java.io.File;
19 import java.util.HashSet;
20 import java.util.Set;
21
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.plugin.MojoExecutionException;
24 import org.apache.maven.plugin.dependency.utils.DependencyStatusSets;
25 import org.apache.maven.plugin.dependency.utils.DependencyUtil;
26 import org.apache.maven.plugin.dependency.utils.resolvers.ArtifactsResolver;
27 import org.apache.maven.plugin.dependency.utils.resolvers.DefaultArtifactsResolver;
28 import org.apache.maven.plugin.dependency.utils.translators.ArtifactTranslator;
29 import org.apache.maven.plugin.dependency.utils.translators.ClassifierTypeTranslator;
30 import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
31 import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
32 import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
33 import org.apache.maven.shared.artifact.filter.collection.ClassifierFilter;
34 import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
35 import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
36 import org.apache.maven.shared.artifact.filter.collection.ProjectTransitivityFilter;
37 import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
38 import org.apache.maven.shared.artifact.filter.collection.TypeFilter;
39 import org.codehaus.plexus.util.StringUtils;
40
41 /**
42 * Class that encapsulates the plugin parameters, and contains methods that
43 * handle dependency filtering
44 *
45 * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
46 * @version $Id: AbstractDependencyFilterMojo.java 1085777 2011-03-26 18:13:19Z hboutemy $
47 * @see org.apache.maven.plugin.dependency.AbstractDependencyMojo
48 */
49 public abstract class AbstractDependencyFilterMojo
50 extends AbstractDependencyMojo
51 {
52 /**
53 * If we should exclude transitive dependencies
54 *
55 * @since 2.0
56 * @optional
57 * @parameter expression="${excludeTransitive}" default-value="false"
58 */
59 protected boolean excludeTransitive;
60
61 /**
62 * Comma Separated list of Types to include. Empty String indicates include
63 * everything (default).
64 *
65 * @since 2.0
66 * @parameter expression="${includeTypes}" default-value=""
67 * @optional
68 */
69 protected String includeTypes;
70
71 /**
72 * Comma Separated list of Types to exclude. Empty String indicates don't
73 * exclude anything (default).
74 *
75 * @since 2.0
76 * @parameter expression="${excludeTypes}" default-value=""
77 * @optional
78 */
79 protected String excludeTypes;
80
81 /**
82 * Scope to include. An Empty string indicates all scopes (default).
83 *
84 * @since 2.0
85 * @parameter expression="${includeScope}" default-value=""
86 * @optional
87 */
88 protected String includeScope;
89
90 /**
91 * Scope to exclude. An Empty string indicates no scopes (default).
92 *
93 * @since 2.0
94 * @parameter expression="${excludeScope}" default-value=""
95 * @optional
96 */
97 protected String excludeScope;
98
99 /**
100 * Comma Separated list of Classifiers to include. Empty String indicates
101 * include everything (default).
102 *
103 * @since 2.0
104 * @parameter expression="${includeClassifiers}" default-value=""
105 * @optional
106 */
107 protected String includeClassifiers;
108
109 /**
110 * Comma Separated list of Classifiers to exclude. Empty String indicates
111 * don't exclude anything (default).
112 *
113 * @since 2.0
114 * @parameter expression="${excludeClassifiers}" default-value=""
115 * @optional
116 */
117 protected String excludeClassifiers;
118
119 /**
120 * Specify classifier to look for. Example: sources
121 *
122 * @optional
123 * @since 2.0
124 * @parameter expression="${classifier}" default-value=""
125 */
126 protected String classifier;
127
128 /**
129 * Specify type to look for when constructing artifact based on classifier.
130 * Example: java-source,jar,war
131 *
132 * @optional
133 * @since 2.0
134 * @parameter expression="${type}" default-value="java-source"
135 */
136 protected String type;
137
138 /**
139 * Comma separated list of Artifact names too exclude.
140 *
141 * @since 2.0
142 * @optional
143 * @parameter expression="${excludeArtifactIds}" default-value=""
144 */
145 protected String excludeArtifactIds;
146
147 /**
148 * Comma separated list of Artifact names to include.
149 *
150 * @since 2.0
151 * @optional
152 * @parameter expression="${includeArtifactIds}" default-value=""
153 */
154 protected String includeArtifactIds;
155
156 /**
157 * Comma separated list of GroupId Names to exclude.
158 *
159 * @since 2.0
160 * @optional
161 * @parameter expression="${excludeGroupIds}" default-value=""
162 */
163 protected String excludeGroupIds;
164
165 /**
166 * Comma separated list of GroupIds to include.
167 *
168 * @since 2.0
169 * @optional
170 * @parameter expression="${includeGroupIds}" default-value=""
171 */
172 protected String includeGroupIds;
173
174 /**
175 * Directory to store flag files
176 *
177 * @parameter expression="${markersDirectory}"
178 * default-value="${project.build.directory}/dependency-maven-plugin-markers"
179 * @optional
180 * @since 2.0
181 */
182 protected File markersDirectory;
183
184 /**
185 * Overwrite release artifacts
186 *
187 * @optional
188 * @since 1.0
189 * @parameter expression="${overWriteReleases}" default-value="false"
190 */
191 protected boolean overWriteReleases;
192
193 /**
194 * Overwrite snapshot artifacts
195 *
196 * @optional
197 * @since 1.0
198 * @parameter expression="${overWriteSnapshots}" default-value="false"
199 */
200 protected boolean overWriteSnapshots;
201
202 /**
203 * Overwrite artifacts that don't exist or are older than the source.
204 *
205 * @optional
206 * @since 2.0
207 * @parameter expression="${overWriteIfNewer}" default-value="true"
208 */
209 protected boolean overWriteIfNewer;
210
211 /**
212 * Prepend the groupId during copy.
213 *
214 * @optional
215 * @since 2.2
216 * @parameter expression="${mdep.prependGroupId}" default-value="false"
217 * @parameter
218 */
219 protected boolean prependGroupId = false;
220
221 protected abstract ArtifactsFilter getMarkedArtifactFilter();
222
223 /**
224 * Retrieves dependencies, either direct only or all including transitive.
225 *
226 * @return A HashSet of artifacts
227 * @throws MojoExecutionException
228 */
229 protected Set<Artifact> getResolvedDependencies( boolean stopOnFailure )
230 throws MojoExecutionException
231
232 {
233 DependencyStatusSets status = getDependencySets( stopOnFailure );
234
235 return status.getResolvedDependencies();
236 }
237
238 /**
239 *
240 * Method creates filters and filters the projects dependencies. This method
241 * also transforms the dependencies if classifier is set. The dependencies
242 * are filtered in least specific to most specific order
243 *
244 * @param stopOnFailure
245 * @return DependencyStatusSets - Bean of TreeSets that contains information
246 * on the projects dependencies
247 * @throws MojoExecutionException
248 */
249 protected DependencyStatusSets getDependencySets( boolean stopOnFailure )
250 throws MojoExecutionException
251 {
252 // add filters in well known order, least specific to most specific
253 FilterArtifacts filter = new FilterArtifacts();
254
255 filter.addFilter( new ProjectTransitivityFilter( project.getDependencyArtifacts(), this.excludeTransitive ) );
256
257 filter.addFilter( new ScopeFilter( DependencyUtil.cleanToBeTokenizedString( this.includeScope ),
258 DependencyUtil.cleanToBeTokenizedString( this.excludeScope ) ) );
259
260 filter.addFilter( new TypeFilter( DependencyUtil.cleanToBeTokenizedString( this.includeTypes ),
261 DependencyUtil.cleanToBeTokenizedString( this.excludeTypes ) ) );
262
263 filter.addFilter( new ClassifierFilter( DependencyUtil.cleanToBeTokenizedString( this.includeClassifiers ),
264 DependencyUtil.cleanToBeTokenizedString( this.excludeClassifiers ) ) );
265
266 filter.addFilter( new GroupIdFilter( DependencyUtil.cleanToBeTokenizedString( this.includeGroupIds ),
267 DependencyUtil.cleanToBeTokenizedString( this.excludeGroupIds ) ) );
268
269 filter.addFilter( new ArtifactIdFilter( DependencyUtil.cleanToBeTokenizedString( this.includeArtifactIds ),
270 DependencyUtil.cleanToBeTokenizedString( this.excludeArtifactIds ) ) );
271
272 // start with all artifacts.
273 Set<Artifact> artifacts = project.getArtifacts();
274
275 // perform filtering
276 try
277 {
278 artifacts = filter.filter( artifacts );
279 }
280 catch ( ArtifactFilterException e )
281 {
282 throw new MojoExecutionException( e.getMessage(), e );
283 }
284
285 // transform artifacts if classifier is set
286 DependencyStatusSets status = null;
287 if ( StringUtils.isNotEmpty( classifier ) )
288 {
289 status = getClassifierTranslatedDependencies( artifacts, stopOnFailure );
290 }
291 else
292 {
293 status = filterMarkedDependencies( artifacts );
294 }
295
296 return status;
297 }
298
299 /**
300 *
301 * Transform artifacts
302 *
303 * @param artifacts
304 * @param stopOnFailure
305 * @return DependencyStatusSets - Bean of TreeSets that contains information
306 * on the projects dependencies
307 * @throws MojoExecutionException
308 */
309 protected DependencyStatusSets getClassifierTranslatedDependencies( Set<Artifact> artifacts, boolean stopOnFailure )
310 throws MojoExecutionException
311 {
312 Set<Artifact> unResolvedArtifacts = new HashSet<Artifact>();
313 Set<Artifact> resolvedArtifacts = artifacts;
314 DependencyStatusSets status = new DependencyStatusSets();
315
316 // possibly translate artifacts into a new set of artifacts based on the
317 // classifier and type
318 // if this did something, we need to resolve the new artifacts
319 if ( StringUtils.isNotEmpty( classifier ) )
320 {
321 ArtifactTranslator translator = new ClassifierTypeTranslator( this.classifier, this.type, this.factory );
322 artifacts = translator.translate( artifacts, getLog() );
323
324 status = filterMarkedDependencies( artifacts );
325
326 // the unskipped artifacts are in the resolved set.
327 artifacts = status.getResolvedDependencies();
328
329 // resolve the rest of the artifacts
330 ArtifactsResolver artifactsResolver = new DefaultArtifactsResolver( this.resolver, this.getLocal(),
331 this.remoteRepos, stopOnFailure );
332 resolvedArtifacts = artifactsResolver.resolve( artifacts, getLog() );
333
334 // calculate the artifacts not resolved.
335 unResolvedArtifacts.addAll( artifacts );
336 unResolvedArtifacts.removeAll( resolvedArtifacts );
337 }
338
339 // return a bean of all 3 sets.
340 status.setResolvedDependencies( resolvedArtifacts );
341 status.setUnResolvedDependencies( unResolvedArtifacts );
342
343 return status;
344 }
345
346 /**
347 * Filter the marked dependencies
348 *
349 * @param artifacts
350 * @return
351 * @throws MojoExecutionException
352 */
353 protected DependencyStatusSets filterMarkedDependencies( Set<Artifact> artifacts )
354 throws MojoExecutionException
355 {
356 // remove files that have markers already
357 FilterArtifacts filter = new FilterArtifacts();
358 filter.clearFilters();
359 filter.addFilter( getMarkedArtifactFilter() );
360
361 Set<Artifact> unMarkedArtifacts;
362 try
363 {
364 unMarkedArtifacts = filter.filter( artifacts );
365 }
366 catch ( ArtifactFilterException e )
367 {
368 throw new MojoExecutionException( e.getMessage(), e );
369 }
370
371 // calculate the skipped artifacts
372 Set<Artifact> skippedArtifacts = new HashSet<Artifact>();
373 skippedArtifacts.addAll( artifacts );
374 skippedArtifacts.removeAll( unMarkedArtifacts );
375
376 return new DependencyStatusSets( unMarkedArtifacts, null, skippedArtifacts );
377 }
378
379 /**
380 * @return Returns the markersDirectory.
381 */
382 public File getMarkersDirectory()
383 {
384 return this.markersDirectory;
385 }
386
387 /**
388 * @param theMarkersDirectory
389 * The markersDirectory to set.
390 */
391 public void setMarkersDirectory( File theMarkersDirectory )
392 {
393 this.markersDirectory = theMarkersDirectory;
394 }
395
396 // TODO: Set marker files.
397
398 /**
399 * @return true, if the groupId should be prepended to the filename.
400 */
401 public boolean isPrependGroupId()
402 {
403 return prependGroupId;
404 }
405
406 /**
407 * @param prependGroupId -
408 * true if the groupId must be prepended during the copy.
409 */
410 public void setPrependGroupId( boolean prependGroupId )
411 {
412 this.prependGroupId = prependGroupId;
413 }
414 }