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.ArchetypeGenerationRequest;
24  import org.apache.maven.archetype.ArchetypeGenerationResult;
25  import org.apache.maven.archetype.ArchetypeManager;
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.plugins.annotations.Component;
35  import org.apache.maven.plugins.annotations.Execute;
36  import org.apache.maven.plugins.annotations.LifecyclePhase;
37  import org.apache.maven.plugins.annotations.Mojo;
38  import org.apache.maven.plugins.annotations.Parameter;
39  import org.apache.maven.shared.invoker.DefaultInvocationRequest;
40  import org.apache.maven.shared.invoker.InvocationRequest;
41  import org.apache.maven.shared.invoker.Invoker;
42  import org.apache.maven.shared.invoker.MavenInvocationException;
43  
44  import java.io.File;
45  import java.util.Arrays;
46  import java.util.List;
47  import java.util.Properties;
48  
49  /**
50   * Generates a new project from an archetype, or updates the actual project if using a partial archetype.
51   * If the project is fully generated, it is generated in a directory corresponding to its artifactId.
52   * If the project is updated with a partial archetype, it is done in the current directory.
53   *
54   * @author rafale
55   */
56  @Mojo( name = "generate", requiresProject = false )
57  @Execute( phase = LifecyclePhase.GENERATE_SOURCES )
58  public class CreateProjectFromArchetypeMojo
59      extends AbstractMojo
60      implements ContextEnabled
61  {
62      @Component
63      private ArchetypeManager manager;
64  
65      @Component
66      private ArchetypeSelector selector;
67  
68      @Component
69      private ArchetypeGenerationConfigurator configurator;
70  
71      @Component
72      private Invoker invoker;
73  
74      /**
75       * The archetype's artifactId.
76       */
77      @Parameter( property = "archetypeArtifactId" )
78      private String archetypeArtifactId;
79  
80      /**
81       * The archetype's groupId.
82       */
83      @Parameter( property = "archetypeGroupId" )
84      private String archetypeGroupId;
85  
86      /**
87       * The archetype's version.
88       */
89      @Parameter( property = "archetypeVersion" )
90      private String archetypeVersion;
91  
92      /**
93       * The archetype's repository.
94       */
95      @Parameter( property = "archetypeRepository" )
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 the 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://repo.maven.apache.org/maven2</code>'</li>;
107      * <li>'<code>internal</code>' which is an internal catalog</li>
108      * </ul>
109      * <p/>
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( property = "archetypeCatalog", defaultValue = "remote,local" )
114     private String archetypeCatalog;
115 
116     /**
117      * Local Maven repository.
118      */
119     @Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
120     private ArtifactRepository localRepository;
121 
122     /**
123      * List of remote repositories used by the resolver.
124      */
125     @Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true )
126     private List<ArtifactRepository> remoteArtifactRepositories;
127 
128     /**
129      * User settings used to check the interactiveMode.
130      */
131     @Parameter( property = "interactiveMode", defaultValue = "${settings.interactiveMode}", required = true )
132     private Boolean interactiveMode;
133 
134     @Parameter( defaultValue = "${basedir}" )
135     private File basedir;
136 
137     @Parameter( defaultValue = "${session}", readonly = true )
138     private MavenSession session;
139 
140     /**
141      * Additional goals to immediately run on the project created from the archetype.
142      */
143     @Parameter( property = "goals" )
144     private String goals;
145 
146     /**
147      * Applying some filter on displayed archetypes list: format is <code>artifactId</code> or <code>groupId:artifactId</code>.
148      * <ul>
149      * <li><code>org.apache:</code> -> displays all archetypes which contain org.apache in groupId</li>
150      * <li><code>:jee</code> or <code>jee</code> -> displays all archetypes which contain jee in artifactId</li>
151      * <li><code>org.apache:jee</code> -> displays all archetypes which contain org.apache in groupId AND jee in artifactId</li>
152      * </ul>
153      *
154      * @since 2.1
155      */
156     @Parameter( property = "filter" )
157     private String filter;
158 
159     public void execute()
160         throws MojoExecutionException, MojoFailureException
161     {
162         Properties executionProperties = session.getExecutionProperties();
163 
164         ArchetypeGenerationRequest request =
165             new ArchetypeGenerationRequest().setArchetypeGroupId( archetypeGroupId ).setArchetypeArtifactId(
166                 archetypeArtifactId ).setArchetypeVersion( archetypeVersion ).setOutputDirectory(
167                 basedir.getAbsolutePath() ).setLocalRepository( localRepository ).setArchetypeRepository(
168                 archetypeRepository ).setRemoteArtifactRepositories( remoteArtifactRepositories ).setFilter( filter );
169 
170         try
171         {
172             if ( interactiveMode.booleanValue() )
173             {
174                 getLog().info( "Generating project in Interactive mode" );
175             }
176             else
177             {
178                 getLog().info( "Generating project in Batch mode" );
179             }
180 
181             selector.selectArchetype( request, interactiveMode, archetypeCatalog );
182 
183             if ( StringUtils.isBlank( request.getArchetypeArtifactId() ) )
184             {
185                 // no archetype found: stopping
186                 return;
187             }
188 
189             configurator.configureArchetype( request, interactiveMode, executionProperties );
190 
191             ArchetypeGenerationResult generationResult = manager.generateProjectFromArchetype( request );
192 
193             if ( generationResult.getCause() != null )
194             {
195                 throw new MojoFailureException( generationResult.getCause(), generationResult.getCause().getMessage(),
196                                                 generationResult.getCause().getMessage() );
197             }
198         }
199         catch ( MojoFailureException ex )
200         {
201             throw ex;
202         }
203         catch ( Exception ex )
204         {
205             throw (MojoFailureException) new MojoFailureException( ex.getMessage() ).initCause( ex );
206         }
207 
208         String artifactId = request.getArtifactId();
209 
210         String postArchetypeGenerationGoals = request.getArchetypeGoals();
211 
212         if ( StringUtils.isEmpty( postArchetypeGenerationGoals ) )
213         {
214             postArchetypeGenerationGoals = goals;
215         }
216 
217         if ( StringUtils.isNotEmpty( postArchetypeGenerationGoals ) )
218         {
219             invokePostArchetypeGenerationGoals( postArchetypeGenerationGoals, artifactId );
220         }
221     }
222 
223     private void invokePostArchetypeGenerationGoals( String goals, String artifactId )
224         throws MojoExecutionException, MojoFailureException
225     {
226         getLog().info( "Invoking post-archetype-generation goals: " + goals );
227 
228         File projectBasedir = new File( basedir, artifactId );
229 
230         if ( projectBasedir.exists() )
231         {
232             InvocationRequest request = new DefaultInvocationRequest().setBaseDirectory( projectBasedir ).setGoals(
233                 Arrays.asList( StringUtils.split( goals, "," ) ) );
234 
235             try
236             {
237                 invoker.execute( request );
238             }
239             catch ( MavenInvocationException e )
240             {
241                 throw new MojoExecutionException( "Cannot run additions goals.", e );
242             }
243         }
244         else
245         {
246             getLog().info( "Post-archetype-generation goals aborted: unavailable basedir " + projectBasedir );
247         }
248     }
249 }