View Javadoc
1   package org.apache.maven.plugins.dependency.fromConfiguration;
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.util.Collections;
24  import java.util.List;
25  
26  import org.apache.maven.artifact.Artifact;
27  import org.apache.maven.artifact.handler.ArtifactHandler;
28  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
29  import org.apache.maven.model.Dependency;
30  import org.apache.maven.plugin.MojoExecutionException;
31  import org.apache.maven.plugin.MojoFailureException;
32  import org.apache.maven.plugins.annotations.Component;
33  import org.apache.maven.plugins.annotations.Parameter;
34  import org.apache.maven.plugins.dependency.AbstractDependencyMojo;
35  import org.apache.maven.plugins.dependency.utils.DependencyUtil;
36  import org.apache.maven.plugins.dependency.utils.filters.ArtifactItemFilter;
37  import org.apache.maven.project.MavenProject;
38  import org.apache.maven.project.ProjectBuildingRequest;
39  import org.apache.maven.shared.artifact.DefaultArtifactCoordinate;
40  import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
41  import org.apache.maven.shared.repository.RepositoryManager;
42  import org.apache.maven.shared.artifact.resolve.ArtifactResolver;
43  import org.apache.maven.shared.artifact.resolve.ArtifactResolverException;
44  import org.codehaus.plexus.util.StringUtils;
45  
46  /**
47   * Abstract parent class used by mojos that get Artifact information from the plugin configuration as an ArrayList of
48   * ArtifactItems
49   *
50   * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
51   * @version $Id: AbstractFromConfigurationMojo.java 1807877 2017-09-09 10:35:59Z khmarbaise $
52   * @see ArtifactItem
53   */
54  public abstract class AbstractFromConfigurationMojo
55      extends AbstractDependencyMojo
56  {
57      /**
58       * Default output location used for mojo, unless overridden in ArtifactItem.
59       *
60       * @since 1.0
61       */
62      @Parameter( property = "outputDirectory", defaultValue = "${project.build.directory}/dependency" )
63      private File outputDirectory;
64  
65      /**
66       * Overwrite release artifacts
67       *
68       * @since 1.0
69       */
70      @Parameter( property = "mdep.overWriteReleases", defaultValue = "false" )
71      private boolean overWriteReleases;
72  
73      /**
74       * Overwrite snapshot artifacts
75       *
76       * @since 1.0
77       */
78      @Parameter( property = "mdep.overWriteSnapshots", defaultValue = "false" )
79      private boolean overWriteSnapshots;
80  
81      /**
82       * Overwrite if newer
83       *
84       * @since 2.0
85       */
86      @Parameter( property = "mdep.overIfNewer", defaultValue = "true" )
87      private boolean overWriteIfNewer;
88  
89      /**
90       * Collection of ArtifactItems to work on. (ArtifactItem contains groupId, artifactId, version, type, classifier,
91       * outputDirectory, destFileName, overWrite and encoding.) See <a href="./usage.html">Usage</a> for details.
92       *
93       * @since 1.0
94       */
95      @Parameter
96      private List<ArtifactItem> artifactItems;
97  
98      /**
99       * Path to override default local repository during plugin's execution. To remove all downloaded artifacts as part
100      * of the build, set this value to a location under your project's target directory
101      *
102      * @since 2.2
103      */
104     @Parameter
105     private File localRepositoryDirectory;
106 
107     @Component
108     private ArtifactResolver artifactResolver;
109 
110     @Component
111     private RepositoryManager repositoryManager;
112 
113     @Component
114     private ArtifactHandlerManager artifactHandlerManager;
115 
116     abstract ArtifactItemFilter getMarkedArtifactFilter( ArtifactItem item );
117 
118     // artifactItems is filled by either field injection or by setArtifact()
119     protected void verifyRequirements()
120         throws MojoFailureException
121     {
122         if ( artifactItems == null || artifactItems.isEmpty() )
123         {
124             throw new MojoFailureException( "Either artifact or artifactItems is required " );
125         }
126     }
127 
128     /**
129      * Preprocesses the list of ArtifactItems. This method defaults the outputDirectory if not set and creates the
130      * output Directory if it doesn't exist.
131      *
132      * @param processArtifactItemsRequest preprocessing instructions
133      * @return An ArrayList of preprocessed ArtifactItems
134      * @throws MojoExecutionException with a message if an error occurs.
135      * @see ArtifactItem
136      */
137     protected List<ArtifactItem> getProcessedArtifactItems( ProcessArtifactItemsRequest processArtifactItemsRequest )
138         throws MojoExecutionException
139     {
140 
141         boolean removeVersion = processArtifactItemsRequest.isRemoveVersion(),
142                         prependGroupId = processArtifactItemsRequest.isPrependGroupId(),
143                         useBaseVersion = processArtifactItemsRequest.isUseBaseVersion();
144 
145         boolean removeClassifier = processArtifactItemsRequest.isRemoveClassifier();
146 
147         if ( artifactItems == null || artifactItems.size() < 1 )
148         {
149             throw new MojoExecutionException( "There are no artifactItems configured." );
150         }
151 
152         for ( ArtifactItem artifactItem : artifactItems )
153         {
154             this.getLog().info( "Configured Artifact: " + artifactItem.toString() );
155 
156             if ( artifactItem.getOutputDirectory() == null )
157             {
158                 artifactItem.setOutputDirectory( this.outputDirectory );
159             }
160             artifactItem.getOutputDirectory().mkdirs();
161 
162             // make sure we have a version.
163             if ( StringUtils.isEmpty( artifactItem.getVersion() ) )
164             {
165                 fillMissingArtifactVersion( artifactItem );
166             }
167 
168             artifactItem.setArtifact( this.getArtifact( artifactItem ) );
169 
170             if ( StringUtils.isEmpty( artifactItem.getDestFileName() ) )
171             {
172                 artifactItem.setDestFileName( DependencyUtil.getFormattedFileName( artifactItem.getArtifact(),
173                                                                                    removeVersion, prependGroupId,
174                                                                                    useBaseVersion, removeClassifier ) );
175             }
176 
177             try
178             {
179                 artifactItem.setNeedsProcessing( checkIfProcessingNeeded( artifactItem ) );
180             }
181             catch ( ArtifactFilterException e )
182             {
183                 throw new MojoExecutionException( e.getMessage(), e );
184             }
185         }
186         return artifactItems;
187     }
188 
189     private boolean checkIfProcessingNeeded( ArtifactItem item )
190         throws MojoExecutionException, ArtifactFilterException
191     {
192         return StringUtils.equalsIgnoreCase( item.getOverWrite(), "true" )
193             || getMarkedArtifactFilter( item ).isArtifactIncluded( item );
194     }
195 
196     /**
197      * Resolves the Artifact from the remote repository if necessary. If no version is specified, it will be retrieved
198      * from the dependency list or from the DependencyManagement section of the pom.
199      *
200      * @param artifactItem containing information about artifact from plugin configuration.
201      * @return Artifact object representing the specified file.
202      * @throws MojoExecutionException with a message if the version can't be found in DependencyManagement.
203      */
204     protected Artifact getArtifact( ArtifactItem artifactItem )
205         throws MojoExecutionException
206     {
207         Artifact artifact;
208 
209         try
210         {
211             // mdep-50 - rolledback for now because it's breaking some functionality.
212             /*
213              * List listeners = new ArrayList(); Set theSet = new HashSet(); theSet.add( artifact );
214              * ArtifactResolutionResult artifactResolutionResult = artifactCollector.collect( theSet, project
215              * .getArtifact(), managedVersions, this.local, project.getRemoteArtifactRepositories(),
216              * artifactMetadataSource, null, listeners ); Iterator iter =
217              * artifactResolutionResult.getArtifactResolutionNodes().iterator(); while ( iter.hasNext() ) {
218              * ResolutionNode node = (ResolutionNode) iter.next(); artifact = node.getArtifact(); }
219              */
220 
221             ProjectBuildingRequest buildingRequest = newResolveArtifactProjectBuildingRequest();
222 
223             if ( localRepositoryDirectory != null )
224             {
225                 buildingRequest =
226                     repositoryManager.setLocalRepositoryBasedir( buildingRequest, localRepositoryDirectory );
227             }
228 
229             // Map dependency to artifact coordinate
230             DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate();
231             coordinate.setGroupId( artifactItem.getGroupId() );
232             coordinate.setArtifactId( artifactItem.getArtifactId() );
233             coordinate.setVersion( artifactItem.getVersion() );
234             coordinate.setClassifier( artifactItem.getClassifier() );
235 
236             final String extension;
237             ArtifactHandler artifactHandler = artifactHandlerManager.getArtifactHandler( artifactItem.getType() );
238             if ( artifactHandler != null )
239             {
240                 extension = artifactHandler.getExtension();
241             }
242             else
243             {
244                 extension = artifactItem.getType();
245             }
246             coordinate.setExtension( extension );
247 
248             artifact = artifactResolver.resolveArtifact( buildingRequest, coordinate ).getArtifact();
249         }
250         catch ( ArtifactResolverException e )
251         {
252             throw new MojoExecutionException( "Unable to find/resolve artifact.", e );
253         }
254 
255         return artifact;
256     }
257 
258     /**
259      * Tries to find missing version from dependency list and dependency management. If found, the artifact is updated
260      * with the correct version. It will first look for an exact match on artifactId/groupId/classifier/type and if it
261      * doesn't find a match, it will try again looking for artifactId and groupId only.
262      *
263      * @param artifact representing configured file.
264      * @throws MojoExecutionException
265      */
266     private void fillMissingArtifactVersion( ArtifactItem artifact )
267         throws MojoExecutionException
268     {
269         MavenProject project = getProject();
270         List<Dependency> deps = project.getDependencies();
271         List<Dependency> depMngt = project.getDependencyManagement() == null ? Collections.<Dependency>emptyList()
272                         : project.getDependencyManagement().getDependencies();
273 
274         if ( !findDependencyVersion( artifact, deps, false )
275             && ( project.getDependencyManagement() == null || !findDependencyVersion( artifact, depMngt, false ) )
276             && !findDependencyVersion( artifact, deps, true )
277             && ( project.getDependencyManagement() == null || !findDependencyVersion( artifact, depMngt, true ) ) )
278         {
279             throw new MojoExecutionException( "Unable to find artifact version of " + artifact.getGroupId() + ":"
280                 + artifact.getArtifactId() + " in either dependency list or in project's dependency management." );
281         }
282     }
283 
284     /**
285      * Tries to find missing version from a list of dependencies. If found, the artifact is updated with the correct
286      * version.
287      *
288      * @param artifact representing configured file.
289      * @param dependencies list of dependencies to search.
290      * @param looseMatch only look at artifactId and groupId
291      * @return the found dependency
292      */
293     private boolean findDependencyVersion( ArtifactItem artifact, List<Dependency> dependencies, boolean looseMatch )
294     {
295         for ( Dependency dependency : dependencies )
296         {
297             if ( StringUtils.equals( dependency.getArtifactId(), artifact.getArtifactId() )
298                 && StringUtils.equals( dependency.getGroupId(), artifact.getGroupId() )
299                 && ( looseMatch || StringUtils.equals( dependency.getClassifier(), artifact.getClassifier() ) )
300                 && ( looseMatch || StringUtils.equals( dependency.getType(), artifact.getType() ) ) )
301             {
302                 artifact.setVersion( dependency.getVersion() );
303 
304                 return true;
305             }
306         }
307 
308         return false;
309     }
310 
311     /**
312      * @return Returns the artifactItems.
313      */
314     public List<ArtifactItem> getArtifactItems()
315     {
316         return this.artifactItems;
317     }
318 
319     /**
320      * @param theArtifactItems The artifactItems to set.
321      */
322     public void setArtifactItems( List<ArtifactItem> theArtifactItems )
323     {
324         this.artifactItems = theArtifactItems;
325     }
326 
327     /**
328      * @return Returns the outputDirectory.
329      */
330     public File getOutputDirectory()
331     {
332         return this.outputDirectory;
333     }
334 
335     /**
336      * @param theOutputDirectory The outputDirectory to set.
337      */
338     public void setOutputDirectory( File theOutputDirectory )
339     {
340         this.outputDirectory = theOutputDirectory;
341     }
342 
343     /**
344      * @return Returns the overWriteIfNewer.
345      */
346     public boolean isOverWriteIfNewer()
347     {
348         return this.overWriteIfNewer;
349     }
350 
351     /**
352      * @param theOverWriteIfNewer The overWriteIfNewer to set.
353      */
354     public void setOverWriteIfNewer( boolean theOverWriteIfNewer )
355     {
356         this.overWriteIfNewer = theOverWriteIfNewer;
357     }
358 
359     /**
360      * @return Returns the overWriteReleases.
361      */
362     public boolean isOverWriteReleases()
363     {
364         return this.overWriteReleases;
365     }
366 
367     /**
368      * @param theOverWriteReleases The overWriteReleases to set.
369      */
370     public void setOverWriteReleases( boolean theOverWriteReleases )
371     {
372         this.overWriteReleases = theOverWriteReleases;
373     }
374 
375     /**
376      * @return Returns the overWriteSnapshots.
377      */
378     public boolean isOverWriteSnapshots()
379     {
380         return this.overWriteSnapshots;
381     }
382 
383     /**
384      * @param theOverWriteSnapshots The overWriteSnapshots to set.
385      */
386     public void setOverWriteSnapshots( boolean theOverWriteSnapshots )
387     {
388         this.overWriteSnapshots = theOverWriteSnapshots;
389     }
390 
391     public void setLocalRepositoryDirectory( File localRepositoryDirectory )
392     {
393         this.localRepositoryDirectory = localRepositoryDirectory;
394     }
395 
396     public void setArtifact( String artifact )
397         throws MojoFailureException
398     {
399         if ( artifact != null )
400         {
401             String packaging = "jar";
402             String classifier;
403             String[] tokens = StringUtils.split( artifact, ":" );
404             if ( tokens.length < 3 || tokens.length > 5 )
405             {
406                 throw new MojoFailureException( "Invalid artifact, "
407                     + "you must specify groupId:artifactId:version[:packaging[:classifier]] " + artifact );
408             }
409             String groupId = tokens[0];
410             String artifactId = tokens[1];
411             String version = tokens[2];
412             if ( tokens.length >= 4 )
413             {
414                 packaging = tokens[3];
415             }
416             if ( tokens.length == 5 )
417             {
418                 classifier = tokens[4];
419             }
420             else
421             {
422                 classifier = null;
423             }
424 
425             ArtifactItem artifactItem = new ArtifactItem();
426             artifactItem.setGroupId( groupId );
427             artifactItem.setArtifactId( artifactId );
428             artifactItem.setVersion( version );
429             artifactItem.setType( packaging );
430             artifactItem.setClassifier( classifier );
431 
432             setArtifactItems( Collections.singletonList( artifactItem ) );
433         }
434     }
435 }