View Javadoc

1   package org.apache.maven.archetype.mojos;
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.commons.lang.StringUtils;
23  import org.apache.maven.archetype.ArchetypeManager;
24  import org.apache.maven.archetype.ArchetypeGenerationRequest;
25  import org.apache.maven.archetype.ArchetypeGenerationResult;
26  import org.apache.maven.archetype.ui.generation.ArchetypeGenerationConfigurator;
27  import org.apache.maven.archetype.ui.generation.ArchetypeSelector;
28  import org.apache.maven.artifact.repository.ArtifactRepository;
29  import org.apache.maven.execution.MavenSession;
30  import org.apache.maven.plugin.AbstractMojo;
31  import org.apache.maven.plugin.ContextEnabled;
32  import org.apache.maven.plugin.MojoExecutionException;
33  import org.apache.maven.plugin.MojoFailureException;
34  import org.apache.maven.shared.invoker.DefaultInvocationRequest;
35  import org.apache.maven.shared.invoker.InvocationRequest;
36  import org.apache.maven.shared.invoker.Invoker;
37  import org.apache.maven.shared.invoker.MavenInvocationException;
38  
39  import java.io.File;
40  import java.util.Arrays;
41  import java.util.List;
42  import java.util.Properties;
43  
44  /**
45   * Generates a new project from an archetype, or updated the actual project if using a partial archetype.
46   * If the project is fully generated, it is generated in a directory corresponding to its artifactId.
47   * If the project is updated with a partial archetype, it is done in the current directory.
48   *
49   * @author rafale
50   * @requiresProject false
51   * @goal generate
52   * @execute phase="generate-sources"
53   */
54  public class CreateProjectFromArchetypeMojo
55      extends AbstractMojo
56      implements ContextEnabled
57  {
58      /** @component */
59      private ArchetypeManager manager;
60  
61      /** @component */
62      private ArchetypeSelector selector;
63  
64      /** @component */
65      private ArchetypeGenerationConfigurator configurator;
66  
67      /** @component */
68      private Invoker invoker;
69  
70      /**
71       * The archetype's artifactId.
72       *
73       * @parameter expression="${archetypeArtifactId}"
74       */
75      private String archetypeArtifactId;
76  
77      /**
78       * The archetype's groupId.
79       *
80       * @parameter expression="${archetypeGroupId}"
81       */
82      private String archetypeGroupId;
83  
84      /**
85       * The archetype's version.
86       *
87       * @parameter expression="${archetypeVersion}"
88       */
89      private String archetypeVersion;
90  
91      /**
92       * The archetype's repository.
93       *
94       * @parameter expression="${archetypeRepository}"
95       */
96      private String archetypeRepository;
97  
98      /**
99       * The archetype catalogs to use to build a list and let the user choose from.
100      * It is a comma separated list of catalogs.
101      * Catalogs use following schemes:
102      * <ul>
103      * <li>'<code>file://...</code>' with <code>archetype-catalog.xml</code> automatically appended when pointing to a directory</li>
104      * <li>'<code>http://...</code>' or '<code>https://...</code>' with <code>archetype-catalog.xml</code> always appended</li>
105      * <li>'<code>local</code>' which is the shortcut for '<code>file://~/.m2/archetype-catalog.xml</code>'</li>
106      * <li>'<code>remote</code>' which is the shortcut for Maven Central repository, ie '<code>http://repo1.maven.org/maven2</code>'</li>
107      * <li>'<code>internal</code>' which is an internal catalog</li>
108      * </ul>
109      *
110      * Since 2.0-alpha-5, default value is no longer <code>internal,local</code> but <code>remote,local</code>.
111      * If Maven Central repository catalog file is empty, <code>internal</code> catalog is used instead.
112      *
113      * @parameter expression="${archetypeCatalog}" default-value="remote,local"
114      */
115     private String archetypeCatalog;
116 
117     /**
118      * Local Maven repository.
119      *
120      * @parameter expression="${localRepository}"
121      * @required
122      * @readonly
123      */
124     private ArtifactRepository localRepository;
125 
126     /**
127      * List of remote repositories used by the resolver.
128      *
129      * @parameter expression="${project.remoteArtifactRepositories}"
130      * @readonly
131      * @required
132      */
133     private List<ArtifactRepository> remoteArtifactRepositories;
134 
135     /**
136      * User settings use to check the interactiveMode.
137      *
138      * @parameter expression="${interactiveMode}" default-value="${settings.interactiveMode}"
139      * @required
140      */
141     private Boolean interactiveMode;
142 
143     /** @parameter expression="${basedir}" */
144     private File basedir;
145 
146     /**
147      *  @parameter expression="${session}"
148      *  @readonly
149      */
150     private MavenSession session;
151 
152     /**
153      * Additional goals to immediately run on the project created from the archetype.
154      *
155      * @parameter expression="${goals}"
156      */
157     private String goals;
158 
159     /**
160      *  Applying some filter on displayed archetypes list: format is <code>artifactId</code> or <code>groupId:artifactId</code>.
161      *  <ul>
162      *    <li><code>org.apache:</code> -> displays all archetypes which contain org.apache in groupId</li>
163      *    <li><code>:jee</code> or <code>jee</code> -> displays all archetypes which contain jee in artifactId</li>
164      *    <li><code>org.apache:jee</code> -> displays all archetypes which contain org.apache in groupId AND jee in artifactId</li>
165      *  </ul>
166      *  @parameter expression="${filter}"
167      *  @since 2.1
168      */
169     private String filter;
170 
171     public void execute()
172         throws MojoExecutionException, MojoFailureException
173     {
174         Properties executionProperties = session.getExecutionProperties();
175 
176         ArchetypeGenerationRequest request = new ArchetypeGenerationRequest()
177             .setArchetypeGroupId( archetypeGroupId )
178             .setArchetypeArtifactId( archetypeArtifactId )
179             .setArchetypeVersion( archetypeVersion )
180             .setOutputDirectory( basedir.getAbsolutePath() )
181             .setLocalRepository( localRepository )
182             .setArchetypeRepository( archetypeRepository )
183             .setRemoteArtifactRepositories( remoteArtifactRepositories )
184             .setFilter( filter );
185 
186         try
187         {
188             if ( interactiveMode.booleanValue() )
189             {
190                 getLog().info( "Generating project in Interactive mode" );
191             }
192             else
193             {
194                 getLog().info( "Generating project in Batch mode" );
195             }
196 
197             selector.selectArchetype( request, interactiveMode, archetypeCatalog );
198 
199             if ( StringUtils.isBlank( request.getArchetypeArtifactId() ) )
200             {
201                 // no archetype found: stopping
202                 return;
203             }
204 
205             configurator.configureArchetype( request, interactiveMode, executionProperties );
206 
207             ArchetypeGenerationResult generationResult = manager.generateProjectFromArchetype( request );
208 
209             if ( generationResult.getCause() != null )
210             {
211                 throw new MojoFailureException( generationResult.getCause(), generationResult.getCause().getMessage(),
212                                                 generationResult.getCause().getMessage() );
213             }
214         }
215         catch ( MojoFailureException ex )
216         {
217             throw ex;
218         }
219         catch ( Exception ex )
220         {
221             throw (MojoFailureException) new MojoFailureException( ex.getMessage() ).initCause( ex );
222         }
223 
224         String artifactId = request.getArtifactId();
225 
226         String postArchetypeGenerationGoals = request.getArchetypeGoals();
227 
228         if ( StringUtils.isEmpty( postArchetypeGenerationGoals ) )
229         {
230             postArchetypeGenerationGoals = goals;
231         }
232 
233         if ( StringUtils.isNotEmpty( postArchetypeGenerationGoals ) )
234         {
235             invokePostArchetypeGenerationGoals( postArchetypeGenerationGoals, artifactId );
236         }
237     }
238 
239     private void invokePostArchetypeGenerationGoals( String goals, String artifactId )
240         throws MojoExecutionException, MojoFailureException
241     {
242         getLog().info( "Invoking post-archetype-generation goals: " + goals );
243 
244         File projectBasedir = new File( basedir, artifactId );
245 
246         if ( projectBasedir.exists() )
247         {
248             InvocationRequest request = new DefaultInvocationRequest()
249                 .setBaseDirectory( projectBasedir )
250                 .setGoals( Arrays.asList( StringUtils.split( goals, "," ) ) );
251 
252             try
253             {
254                 invoker.execute( request );
255             }
256             catch ( MavenInvocationException e )
257             {
258                 throw new MojoExecutionException( "Cannot run additions goals.", e );
259             }
260         }
261         else
262         {
263             getLog().info( "Post-archetype-generation goals aborted: unavailable basedir " + projectBasedir );
264         }
265     }
266 }