View Javadoc
1   package org.apache.maven.plugins.help;
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.RepositoryUtils;
23  import org.apache.maven.artifact.Artifact;
24  import org.apache.maven.artifact.repository.ArtifactRepository;
25  import org.apache.maven.execution.MavenSession;
26  import org.apache.maven.model.building.ModelBuildingRequest;
27  import org.apache.maven.plugin.AbstractMojo;
28  import org.apache.maven.plugin.MojoExecutionException;
29  import org.apache.maven.plugins.annotations.Component;
30  import org.apache.maven.plugins.annotations.Parameter;
31  import org.apache.maven.project.DefaultProjectBuildingRequest;
32  import org.apache.maven.project.MavenProject;
33  import org.apache.maven.project.ProjectBuilder;
34  import org.apache.maven.project.ProjectBuildingRequest;
35  import org.codehaus.plexus.util.StringUtils;
36  import org.codehaus.plexus.util.WriterFactory;
37  import org.eclipse.aether.RepositoryException;
38  import org.eclipse.aether.RepositorySystem;
39  import org.eclipse.aether.RepositorySystemSession;
40  import org.eclipse.aether.artifact.DefaultArtifact;
41  import org.eclipse.aether.repository.RemoteRepository;
42  import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
43  import org.eclipse.aether.resolution.ArtifactDescriptorResult;
44  import org.eclipse.aether.resolution.ArtifactRequest;
45  
46  import java.io.File;
47  import java.io.IOException;
48  import java.io.Writer;
49  import java.util.List;
50  
51  /**
52   * Base class with some Help Mojo functionalities.
53   *
54   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
55   * @since 2.1
56   */
57  public abstract class AbstractHelpMojo
58      extends AbstractMojo
59  {
60      /** The maximum length of a display line. */
61      protected static final int LINE_LENGTH = 79;
62      
63      /** The line separator for the current OS. */
64      protected static final String LS = System.getProperty( "line.separator" );
65      
66      /**
67       * Maven Project Builder component.
68       */
69      @Component
70      protected ProjectBuilder projectBuilder;
71  
72      /**
73       * Component used to resolve artifacts and download their files from remote repositories.
74       */
75      @Component
76      protected RepositorySystem repositorySystem;
77  
78      /**
79       * Remote repositories used for the project.
80       */
81      @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
82      protected List<ArtifactRepository> remoteRepositories;
83  
84      /**
85       * Plugin repositories used for the project.
86       */
87      @Parameter( defaultValue = "${project.pluginArtifactRepositories}", required = true, readonly = true )
88      protected List<ArtifactRepository> pluginArtifactRepositories;
89  
90      /**
91       * Local Repository.
92       */
93      @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
94      protected ArtifactRepository localRepository;
95      
96      /**
97       * The current build session instance. This is used for
98       * plugin manager API calls.
99       */
100     @Parameter( defaultValue = "${session}", readonly = true, required = true )
101     protected MavenSession session;
102 
103     /**
104      * Optional parameter to write the output of this help in a given file, instead of writing to the console.
105      * <br>
106      * <b>Note</b>: Could be a relative path.
107      */
108     @Parameter( property = "output" )
109     protected File output;
110 
111     /**
112      * Utility method to write a content in a given file.
113      *
114      * @param output is the wanted output file.
115      * @param content contains the content to be written to the file.
116      * @throws IOException if any
117      * @see #writeFile(File, String)
118      */
119     protected static void writeFile( File output, StringBuilder content )
120         throws IOException
121     {
122         writeFile( output, content.toString() );
123     }
124 
125     /**
126      * Utility method to write a content in a given file.
127      *
128      * @param output is the wanted output file.
129      * @param content contains the content to be written to the file.
130      * @throws IOException if any
131      */
132     protected static void writeFile( File output, String content )
133         throws IOException
134     {
135         if ( output == null )
136         {
137             return;
138         }
139 
140         output.getParentFile().mkdirs();
141         try ( Writer out = WriterFactory.newPlatformWriter( output ) )
142         {
143             out.write( content );
144         }
145     }
146     
147     /**
148      * Parses the given String into GAV artifact coordinate information, adding the given type.
149      * 
150      * @param artifactString should respect the format <code>groupId:artifactId[:version]</code>
151      * @param type The extension for the artifact, must not be <code>null</code>.
152      * @return the <code>Artifact</code> object for the <code>artifactString</code> parameter.
153      * @throws MojoExecutionException if the <code>artifactString</code> doesn't respect the format.
154      */
155     protected org.eclipse.aether.artifact.Artifact getAetherArtifact( String artifactString, String type )
156         throws MojoExecutionException
157     {
158         if ( StringUtils.isEmpty( artifactString ) )
159         {
160             throw new IllegalArgumentException( "artifact parameter could not be empty" );
161         }
162 
163         String groupId; // required
164         String artifactId; // required
165         String version; // optional
166 
167         String[] artifactParts = artifactString.split( ":" );
168         switch ( artifactParts.length )
169         {
170             case 2:
171                 groupId = artifactParts[0];
172                 artifactId = artifactParts[1];
173                 version = Artifact.LATEST_VERSION;
174                 break;
175             case 3:
176                 groupId = artifactParts[0];
177                 artifactId = artifactParts[1];
178                 version = artifactParts[2];
179                 break;
180             default:
181                 throw new MojoExecutionException( "The artifact parameter '" + artifactString
182                     + "' should be conform to: " + "'groupId:artifactId[:version]'." );
183         }
184 
185         return new DefaultArtifact( groupId, artifactId, type, version );
186     }
187 
188     /**
189      * Retrieves the Maven Project associated with the given artifact String, in the form of
190      * <code>groupId:artifactId[:version]</code>. This resolves the POM artifact at those coordinates and then builds
191      * the Maven project from it.
192      * 
193      * @param artifactString Coordinates of the Maven project to get.
194      * @return New Maven project.
195      * @throws MojoExecutionException If there was an error while getting the Maven project.
196      */
197     protected MavenProject getMavenProject( String artifactString )
198         throws MojoExecutionException
199     {
200         try
201         {
202             ProjectBuildingRequest pbr = new DefaultProjectBuildingRequest( session.getProjectBuildingRequest() );
203             pbr.setRemoteRepositories( remoteRepositories );
204             pbr.setLocalRepository( localRepository );
205             pbr.setPluginArtifactRepositories( pluginArtifactRepositories );
206             pbr.setProject( null );
207             pbr.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
208             pbr.setResolveDependencies( true );
209 
210             org.eclipse.aether.artifact.Artifact artifact = resolveArtifact(
211                     getAetherArtifact( artifactString, "pom" ) ).getArtifact();
212 
213             return projectBuilder.build( artifact.getFile(), pbr ).getProject();
214         }
215         catch ( Exception e )
216         {
217             throw new MojoExecutionException( "Unable to get the POM for the artifact '" + artifactString
218                 + "'. Verify the artifact parameter.", e );
219         }
220     }
221 
222     protected org.eclipse.aether.resolution.ArtifactResult resolveArtifact(
223             org.eclipse.aether.artifact.Artifact artifact ) throws RepositoryException
224     {
225         List<RemoteRepository> repositories = RepositoryUtils.toRepos( remoteRepositories );
226         RepositorySystemSession repositorySession = session.getProjectBuildingRequest().getRepositorySession();
227 
228         // use descriptor to respect relocation
229         ArtifactDescriptorResult artifactDescriptor = repositorySystem.readArtifactDescriptor(
230                 repositorySession, new ArtifactDescriptorRequest( artifact, repositories, null ) );
231 
232         return repositorySystem.resolveArtifact( repositorySession,
233                 new ArtifactRequest( artifactDescriptor.getArtifact(), repositories, null ) );
234     }
235 
236 }