View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a 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,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.maven.archetype.mojos;
21  
22  import java.io.IOException;
23  import org.apache.maven.archetype.ArchetypeCreationRequest;
24  import org.apache.maven.archetype.ArchetypeCreationResult;
25  import org.apache.maven.archetype.Archetype;
26  import org.apache.maven.archetype.common.ArchetypeRegistryManager;
27  import org.apache.maven.archetype.ui.ArchetypeCreationConfigurator;
28  import org.apache.maven.artifact.repository.ArtifactRepository;
29  import org.apache.maven.plugin.AbstractMojo;
30  import org.apache.maven.plugin.MojoExecutionException;
31  import org.apache.maven.plugin.MojoFailureException;
32  import org.apache.maven.project.MavenProject;
33  
34  import java.io.File;
35  import java.io.FileInputStream;
36  import java.util.ArrayList;
37  import java.util.Arrays;
38  import java.util.List;
39  import java.util.Properties;
40  import org.apache.maven.archetype.common.Constants;
41  import org.apache.maven.execution.MavenSession;
42  import org.codehaus.plexus.util.StringUtils;
43  
44  /**
45   * Creates an archetype from the current project.
46   *
47   * @author rafale
48   * @requiresProject true
49   * @goal create-from-project
50   * @execute phase="generate-sources"
51   * @aggregator
52   */
53  public class CreateArchetypeFromProjectMojo
54      extends AbstractMojo
55  {
56      /** @component */
57      ArchetypeCreationConfigurator configurator;
58  
59      /**
60       * Enable the interactive mode to define the archetype from the project.
61       *
62       * @parameter expression="${interactive}" default-value="false"
63       */
64      private boolean interactive;
65  
66      /** @component */
67      ArchetypeRegistryManager archetypeRegistryManager;
68  
69      /** @component */
70      Archetype archetype;
71  
72      /**
73       * File extensions which are checked for project's text files (vs binary files).
74       *
75       * @parameter expression="${archetype.filteredExtentions}"
76       */
77      private String archetypeFilteredExtentions;
78  
79      /**
80       * Directory names which are checked for project's sources main package.
81       *
82       * @parameter expression="${archetype.languages}"
83       */
84      private String archetypeLanguages;
85  
86      /**
87       * The location of the registry file.
88       *
89       * @parameter expression="${user.home}/.m2/archetype.xml"
90       */
91      private File archetypeRegistryFile;
92  
93      /**
94       * Velocity templates encoding.
95       *
96       * @parameter default-value="UTF-8" expression="${archetype.encoding}"
97       */
98      private String defaultEncoding;
99  
100     /**
101      * Create a partial archetype.
102      *
103      * @parameter expression="${archetype.partialArchetype}"
104      */
105     private boolean partialArchetype = false;
106 
107     /**
108      * Create pom's velocity templates with CDATA preservation. This uses the <code>String.replaceAll()</code>
109      * method and risks to have some overly replacement capabilities (beware of '1.0' value).
110      *
111      * @parameter expression="${archetype.preserveCData}"
112      */
113     private boolean preserveCData = false;
114 
115     /** @parameter expression="${localRepository}" */
116     private ArtifactRepository localRepository;
117 
118     /**
119      * Poms in archetype are created with their initial parent.
120      * This property is ignored when preserveCData is true.
121      *
122      * @parameter expression="${archetype.keepParent}"
123      */
124     private boolean keepParent = true;
125 
126     /**
127      * The maven Project to create an archetype from.
128      *
129      * @parameter expression="${project}"
130      * @required
131      * @readonly
132      */
133     private MavenProject project;
134 
135     /**
136      * The property file that holds the plugin configuration.
137      *
138      * @parameter expression="${archetype.properties}"
139      */
140     private File propertyFile;
141 
142     /**
143      * The property telling which phase to call on the generated archetype.
144      * Interesting values are: <code>package</code>, <code>install</code> and <code>deploy</code>
145      *
146      * @parameter expression="${archetype.postPhase}" default-value="package"
147      */
148     private String archetypePostPhase;
149 
150     /** @parameter expression="${project.build.directory}" */
151     private File outputDirectory;
152 
153     /** @parameter expression="${testMode}" */
154     private boolean testMode;
155 
156     /** @parameter expression="${packageName}" */
157     private String packageName;//Find a better way to resolve the package!!! enforce usage of the configurator
158 
159     /**
160      *  @parameter expression="${session}"
161      *  @readonly
162      */
163     private MavenSession session;
164 
165     public void execute()
166         throws MojoExecutionException, MojoFailureException
167     {
168         Properties executionProperties = session.getExecutionProperties();
169         try
170         {
171             if ( propertyFile != null )
172             {
173                 propertyFile.getParentFile().mkdirs();
174             }
175 
176             List languages = getLanguages( archetypeLanguages, propertyFile );
177 
178             Properties properties =
179                 configurator.configureArchetypeCreation( project, Boolean.valueOf( interactive ), executionProperties,
180                                                          propertyFile, languages );
181 
182             List filtereds = getFilteredExtensions( archetypeFilteredExtentions, propertyFile );
183 
184             ArchetypeCreationRequest request = new ArchetypeCreationRequest()
185                 .setProject( project )
186                 /*Used when in interactive mode*/
187                 .setProperties( properties )
188                 .setLanguages( languages )
189                 /*Should be refactored to use some ant patterns*/
190                 .setFiltereds( filtereds )
191                 /*This should be correctly handled*/
192                 .setPreserveCData( preserveCData )
193                 .setKeepParent( keepParent )
194                 .setPartialArchetype( partialArchetype )
195                 /*This should be used before there and use only languages and filtereds*/
196                 .setArchetypeRegistryFile( archetypeRegistryFile )
197                 .setLocalRepository( localRepository )
198                 /*this should be resolved and asked for user to verify*/
199                 .setPackageName(packageName)
200                 .setPostPhase( archetypePostPhase );
201 
202             ArchetypeCreationResult result = archetype.createArchetypeFromProject( request );
203 
204             if ( result.getCause() != null )
205             {
206                 throw new MojoFailureException( result.getCause(), result.getCause().getMessage(),
207                                                 result.getCause().getMessage() );
208             }
209 
210             getLog().info( "Archetype created in target/generated-sources/archetype" );
211 
212             if ( testMode )
213             {
214                 // Now here a properties file would be useful to write so that we could automate
215                 // some functional tests where we string together an:
216                 //
217                 // archetype create from project -> deploy it into a test repo
218                 // project create from archetype -> use the repository we deployed to archetype to
219                 // generate
220                 // test the output
221                 //
222                 // This of course would be strung together from the outside.
223             }
224 
225         }
226         catch ( MojoFailureException ex )
227         {
228             throw ex;
229         }
230         catch ( Exception ex )
231         {
232             throw new MojoFailureException( ex, ex.getMessage(), ex.getMessage() );
233         }
234     }
235 
236     private List getFilteredExtensions( String archetypeFilteredExtentions, File propertyFile )
237     {
238         List filteredExtensions = new ArrayList();
239 
240         if ( StringUtils.isNotEmpty( archetypeFilteredExtentions ) )
241         {
242             filteredExtensions.addAll( Arrays.asList( StringUtils.split( archetypeFilteredExtentions, "," ) ) );
243 
244             getLog().debug( "Found in command line extensions = " + filteredExtensions );
245         }
246 
247         if ( filteredExtensions.isEmpty() && propertyFile != null && propertyFile.exists() )
248         {
249             try
250             {
251                 Properties properties = new Properties();
252                 properties.load( new FileInputStream( propertyFile ) );
253 
254                 String extensions = properties.getProperty( Constants.ARCHETYPE_FILTERED_EXTENSIONS );
255                 if ( StringUtils.isNotEmpty( extensions ) )
256                 {
257                     filteredExtensions.addAll( Arrays.asList( StringUtils.split( extensions, "," ) ) );
258                 }
259 
260                 getLog().debug(
261                                 "Found in propertyFile " + propertyFile.getName() + " extensions = "
262                                     + filteredExtensions );
263             }
264             catch ( IOException e )
265             {
266                 getLog().warn( "Can not read " + propertyFile.getName() );
267             }
268         }
269 
270         if ( filteredExtensions.isEmpty() )
271         {
272             filteredExtensions.addAll( Constants.DEFAULT_FILTERED_EXTENSIONS );
273 
274             getLog().debug( "Using default extensions = " + filteredExtensions );
275         }
276 
277         return filteredExtensions;
278     }
279 
280     private List getLanguages( String archetypeLanguages, File propertyFile )
281     {
282         List resultingLanguages = new ArrayList();
283 
284         if ( StringUtils.isNotEmpty( archetypeLanguages ) )
285         {
286             resultingLanguages.addAll( Arrays.asList( StringUtils.split( archetypeLanguages, "," ) ) );
287 
288             getLog().debug( "Found in command line languages = " + resultingLanguages );
289         }
290 
291         if ( resultingLanguages.isEmpty() && propertyFile != null && propertyFile.exists() )
292         {
293             try
294             {
295                 Properties properties = new Properties();
296                 properties.load( new FileInputStream( propertyFile ) );
297 
298                 String languages = properties.getProperty( Constants.ARCHETYPE_LANGUAGES );
299                 if ( StringUtils.isNotEmpty( languages ) )
300                 {
301                     resultingLanguages.addAll( Arrays.asList( StringUtils.split( languages, "," ) ) );
302                 }
303 
304                 getLog().debug(
305                                 "Found in propertyFile " + propertyFile.getName() + " languages = "
306                                     + resultingLanguages );
307             }
308             catch( IOException e )
309             {
310                 getLog().warn( "Can not read " + propertyFile.getName() );
311             }
312         }
313 
314         if ( resultingLanguages.isEmpty() )
315         {
316             resultingLanguages.addAll( Constants.DEFAULT_LANGUAGES );
317 
318             getLog().debug( "Using default languages = " + resultingLanguages );
319         }
320 
321         return resultingLanguages;
322     }
323 }