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.maven.archetype.ArchetypeCreationRequest;
23  import org.apache.maven.archetype.ArchetypeCreationResult;
24  import org.apache.maven.archetype.ArchetypeManager;
25  import org.apache.maven.archetype.common.Constants;
26  import org.apache.maven.archetype.ui.creation.ArchetypeCreationConfigurator;
27  import org.apache.maven.artifact.repository.ArtifactRepository;
28  import org.apache.maven.execution.MavenSession;
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  import org.codehaus.plexus.util.PropertyUtils;
34  import org.codehaus.plexus.util.StringUtils;
35  
36  import java.io.File;
37  import java.util.ArrayList;
38  import java.util.Arrays;
39  import java.util.List;
40  import java.util.Properties;
41  
42  /**
43   * Creates an archetype project from the current project, with a <code>basic</code> integration-test.
44   *
45   * @author rafale
46   * @requiresProject true
47   * @goal create-from-project
48   * @execute phase="generate-sources"
49   * @aggregator
50   */
51  public class CreateArchetypeFromProjectMojo
52      extends AbstractMojo
53  {
54      /** @component */
55      private ArchetypeCreationConfigurator configurator;
56  
57      /**
58       * Enable the interactive mode to define the archetype from the project.
59       *
60       * @parameter expression="${interactive}" default-value="false"
61       */
62      private boolean interactive;
63  
64      /** @component */
65      private ArchetypeManager manager;
66  
67      /**
68       * File extensions which are checked for project's text files (vs binary files).
69       *
70       * @parameter expression="${archetype.filteredExtentions}"
71       */
72      private String archetypeFilteredExtentions;
73  
74      /**
75       * Directory names which are checked for project's sources main package.
76       *
77       * @parameter expression="${archetype.languages}"
78       */
79      private String archetypeLanguages;
80  
81      /**
82       * The location of the registry file.
83       *
84       * @parameter expression="${user.home}/.m2/archetype.xml"
85       */
86      private File archetypeRegistryFile;
87  
88      /**
89       * Velocity templates encoding.
90       *
91       * @parameter default-value="UTF-8" expression="${archetype.encoding}"
92       */
93      private String defaultEncoding;
94  
95      /**
96       * Create a partial archetype.
97       *
98       * @parameter expression="${archetype.partialArchetype}"
99       */
100     private boolean partialArchetype = false;
101 
102     /**
103      * Create pom's velocity templates with CDATA preservation. This uses the <code>String.replaceAll()</code>
104      * method and risks to have some overly replacement capabilities (beware of '1.0' value).
105      *
106      * @parameter expression="${archetype.preserveCData}"
107      */
108     private boolean preserveCData = false;
109 
110     /** @parameter expression="${localRepository}" */
111     private ArtifactRepository localRepository;
112 
113     /**
114      * POMs in archetype are created with their initial parent.
115      * This property is ignored when preserveCData is true.
116      *
117      * @parameter expression="${archetype.keepParent}"
118      */
119     private boolean keepParent = true;
120 
121     /**
122      * The Maven project to create an archetype from.
123      *
124      * @parameter expression="${project}"
125      * @required
126      * @readonly
127      */
128     private MavenProject project;
129 
130     /**
131      * The property file that holds the plugin configuration.
132      *
133      * @parameter expression="${archetype.properties}"
134      */
135     private File propertyFile;
136 
137     /**
138      * The property telling which phase to call on the generated archetype.
139      * Interesting values are: <code>package</code>, <code>integration-test</code>, <code>install</code> and <code>deploy</code>.
140      *
141      * @parameter expression="${archetype.postPhase}" default-value="package"
142      */
143     private String archetypePostPhase;
144 
145     /**
146      * The directory where the archetype should be created.
147      * 
148      * @parameter expression="${project.build.directory}/generated-sources/archetype"
149      */
150     private File outputDirectory;
151 
152     /** @parameter expression="${testMode}" */
153     private boolean testMode;
154 
155     /** @parameter expression="${packageName}" */
156     private String packageName; //Find a better way to resolve the package!!! enforce usage of the configurator
157 
158     /**
159      *  @parameter expression="${session}"
160      *  @readonly
161      */
162     private MavenSession session;
163 
164     public void execute()
165         throws MojoExecutionException, MojoFailureException
166     {
167         Properties executionProperties = session.getExecutionProperties();
168         try
169         {
170             if ( propertyFile != null )
171             {
172                 propertyFile.getParentFile().mkdirs();
173             }
174 
175             List<String> languages = getLanguages( archetypeLanguages, propertyFile );
176 
177             Properties properties =
178                 configurator.configureArchetypeCreation( project, Boolean.valueOf( interactive ), executionProperties,
179                                                          propertyFile, languages );
180 
181             List<String> filtereds = getFilteredExtensions( archetypeFilteredExtentions, propertyFile );
182 
183             ArchetypeCreationRequest request = new ArchetypeCreationRequest()
184                 .setProject( project )
185                 /* Used when in interactive mode */
186                 .setProperties( properties )
187                 .setLanguages( languages )
188                 /* Should be refactored to use some ant patterns */
189                 .setFiltereds( filtereds )
190                 /* This should be correctly handled */
191                 .setPreserveCData( preserveCData )
192                 .setKeepParent( keepParent )
193                 .setPartialArchetype( partialArchetype )
194                 /* This should be used before there and use only languages and filtereds */
195                 .setArchetypeRegistryFile( archetypeRegistryFile )
196                 .setLocalRepository( localRepository )
197                 /* this should be resolved and asked for user to verify */
198                 .setPackageName( packageName )
199                 .setPostPhase( archetypePostPhase )
200                 .setOutputDirectory( outputDirectory );
201 
202             ArchetypeCreationResult result = manager.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 " + outputDirectory );
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<String> getFilteredExtensions( String archetypeFilteredExtentions, File propertyFile )
237     {
238         List<String> filteredExtensions = new ArrayList<String>();
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             Properties properties = PropertyUtils.loadProperties( propertyFile );
250 
251             String extensions = properties.getProperty( Constants.ARCHETYPE_FILTERED_EXTENSIONS );
252             if ( StringUtils.isNotEmpty( extensions ) )
253             {
254                 filteredExtensions.addAll( Arrays.asList( StringUtils.split( extensions, "," ) ) );
255             }
256 
257             getLog().debug( "Found in propertyFile " + propertyFile.getName() + " extensions = " + filteredExtensions );
258         }
259 
260         if ( filteredExtensions.isEmpty() )
261         {
262             filteredExtensions.addAll( Constants.DEFAULT_FILTERED_EXTENSIONS );
263 
264             getLog().debug( "Using default extensions = " + filteredExtensions );
265         }
266 
267         return filteredExtensions;
268     }
269 
270     private List<String> getLanguages( String archetypeLanguages, File propertyFile )
271     {
272         List<String> resultingLanguages = new ArrayList<String>();
273 
274         if ( StringUtils.isNotEmpty( archetypeLanguages ) )
275         {
276             resultingLanguages.addAll( Arrays.asList( StringUtils.split( archetypeLanguages, "," ) ) );
277 
278             getLog().debug( "Found in command line languages = " + resultingLanguages );
279         }
280 
281         if ( resultingLanguages.isEmpty() && propertyFile != null && propertyFile.exists() )
282         {
283             Properties properties = PropertyUtils.loadProperties( propertyFile );
284 
285             String languages = properties.getProperty( Constants.ARCHETYPE_LANGUAGES );
286             if ( StringUtils.isNotEmpty( languages ) )
287             {
288                 resultingLanguages.addAll( Arrays.asList( StringUtils.split( languages, "," ) ) );
289             }
290 
291             getLog().debug( "Found in propertyFile " + propertyFile.getName() + " languages = " + resultingLanguages );
292         }
293 
294         if ( resultingLanguages.isEmpty() )
295         {
296             resultingLanguages.addAll( Constants.DEFAULT_LANGUAGES );
297 
298             getLog().debug( "Using default languages = " + resultingLanguages );
299         }
300 
301         return resultingLanguages;
302     }
303 }