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 sample archetype from 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 preservasion. This uses the String replaceAll
109      * method and risk 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     /** @parameter expression="${basedir}/target" */
143     private File outputDirectory;
144 
145     /** @parameter expression="${testMode}" */
146     private boolean testMode;
147 
148     /** @parameter expression="${packageName}" */
149     private String packageName;//Find a better way to resolve the package!!! enforce usage of the configurator
150 
151     /** 
152      *  @parameter expression="${session}" 
153      *  @readonly
154      */
155     private MavenSession session;
156 
157     public void execute()
158         throws
159         MojoExecutionException,
160         MojoFailureException
161     {
162         Properties executionProperties = session.getExecutionProperties();
163         try
164         {
165             if ( propertyFile != null )
166             {
167                 propertyFile.getParentFile().mkdirs();
168             }
169 
170             List languages = getLanguages( archetypeLanguages, propertyFile );
171 
172             Properties properties = configurator.configureArchetypeCreation(
173                 project,
174                 new Boolean( interactive ),
175                 executionProperties,
176                 propertyFile,
177                 languages
178             );
179 
180             List filtereds =
181                 getFilteredExtensions(
182                     archetypeFilteredExtentions,
183                     propertyFile
184                 );
185             
186             ArchetypeCreationRequest request = new ArchetypeCreationRequest()
187                 .setProject( project )
188                 /*Used when in interactive mode*/
189                 .setProperties( properties )
190                 .setLanguages( languages )
191                 /*Should be refactored to use some ant patterns*/
192                 .setFiltereds( filtereds )
193                 /*This should be correctly handled*/
194                 .setPreserveCData( preserveCData )
195                 .setKeepParent( keepParent )
196                 .setPartialArchetype( partialArchetype )
197                 /*This should be used before there and use only languages and filtereds*/
198                 .setArchetypeRegistryFile( archetypeRegistryFile )
199                 .setLocalRepository( localRepository )
200                 /*this should be resolved and asked for user to verify*/
201                 .setPackageName(packageName);
202 
203             ArchetypeCreationResult result = archetype.createArchetypeFromProject( request );
204 
205             if( result.getCause() != null )
206             {
207                 throw new MojoFailureException(
208                     result.getCause(),
209                     result.getCause().getMessage(),
210                     result.getCause().getMessage()
211                 );
212             }
213 
214             getLog().info( "Archetype created in target/generated-sources/archetype" );
215 
216             if ( testMode )
217             {
218                 // Now here a properties file would be useful to write so that we could automate
219                 // some functional tests where we string together an:
220                 //
221                 // archetype create from project -> deploy it into a test repo
222                 // project create from archetype -> use the repository we deployed to archetype to
223                 // generate
224                 // test the output
225                 //
226                 // This of course would be strung together from the outside.
227             }
228 
229         }
230         catch ( MojoFailureException ex )
231         {
232             throw ex;
233         }
234         catch ( Exception ex )
235         {
236             throw new MojoFailureException( ex, ex.getMessage(), ex.getMessage() );
237         }
238     }
239 
240     private List getFilteredExtensions( String archetypeFilteredExtentions, File propertyFile )
241     {
242         List filteredExtensions = new ArrayList();
243 
244         if( StringUtils.isNotEmpty( archetypeFilteredExtentions ) )
245         {
246             filteredExtensions.addAll(
247                 Arrays.asList( StringUtils.split( archetypeFilteredExtentions, "," ) )
248             );
249             getLog().debug("Found in command line extensions = " + filteredExtensions);
250         }
251 
252         if( filteredExtensions.isEmpty() && propertyFile != null && propertyFile.exists() )
253         {
254             try
255             {
256                 Properties properties = new Properties();
257                 properties.load( new FileInputStream( propertyFile ) );
258 
259                 String extensions =
260                     properties.getProperty( Constants.ARCHETYPE_FILTERED_EXTENSIONS );
261                 if( StringUtils.isNotEmpty( extensions ) )
262                 {
263                     filteredExtensions.addAll(
264                         Arrays.asList( StringUtils.split( extensions, "," ) )
265                     );
266                 }
267             getLog().debug("Found in propertyFile " +  propertyFile.getName() + " extensions = " + filteredExtensions);
268             }
269             catch( IOException e )
270             {
271                 getLog().warn( "Can not read " + propertyFile.getName() );
272             }
273         }
274 
275         if( filteredExtensions.isEmpty() )
276         {
277             filteredExtensions.addAll( Constants.DEFAULT_FILTERED_EXTENSIONS );
278             getLog().debug("Using default extensions = " + filteredExtensions);
279         }
280 
281         return filteredExtensions;
282     }
283 
284     private List getLanguages(String archetypeLanguages, File propertyFile) {
285         List resultingLanguages = new ArrayList();
286 
287         if ( StringUtils.isNotEmpty( archetypeLanguages ) )
288         {
289             resultingLanguages.addAll( Arrays.asList( StringUtils.split( archetypeLanguages, "," ) ) );
290             getLog().debug("Found in command line languages = " + resultingLanguages);
291         }
292 
293         if( resultingLanguages.isEmpty() && propertyFile != null && propertyFile.exists() )
294         {
295             try
296             {
297                 Properties properties = new Properties();
298                 properties.load( new FileInputStream( propertyFile ) );
299 
300                 String languages =
301                     properties.getProperty( Constants.ARCHETYPE_LANGUAGES );
302                 if( StringUtils.isNotEmpty( languages ) )
303                 {
304                     resultingLanguages.addAll(
305                         Arrays.asList( StringUtils.split( languages, "," ) )
306                     );
307                 }
308             getLog().debug("Found in propertyFile " +  propertyFile.getName() + " languages = " + resultingLanguages);
309             }
310             catch( IOException e )
311             {
312                 getLog().warn( "Can not read " + propertyFile.getName() );
313             }
314         }
315 
316         if ( resultingLanguages.isEmpty() )
317         {
318             resultingLanguages.addAll( Constants.DEFAULT_LANGUAGES );
319             getLog().debug("Using default languages = " + resultingLanguages);
320         }
321 
322         return resultingLanguages;
323     }
324 }