View Javadoc

1   package org.apache.maven.archetype.ui.creation;
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.common.ArchetypeFilesResolver;
23  import org.apache.maven.archetype.common.Constants;
24  import org.apache.maven.archetype.exception.ArchetypeNotConfigured;
25  import org.apache.maven.archetype.exception.ArchetypeNotDefined;
26  import org.apache.maven.archetype.exception.TemplateCreationException;
27  import org.apache.maven.archetype.ui.ArchetypeConfiguration;
28  import org.apache.maven.archetype.ui.ArchetypeDefinition;
29  import org.apache.maven.archetype.ui.ArchetypeFactory;
30  import org.apache.maven.project.MavenProject;
31  import org.codehaus.plexus.component.annotations.Component;
32  import org.codehaus.plexus.component.annotations.Requirement;
33  import org.codehaus.plexus.components.interactivity.PrompterException;
34  import org.codehaus.plexus.logging.AbstractLogEnabled;
35  import org.codehaus.plexus.util.IOUtil;
36  import org.codehaus.plexus.util.StringUtils;
37  
38  import java.io.File;
39  import java.io.FileInputStream;
40  import java.io.FileNotFoundException;
41  import java.io.FileOutputStream;
42  import java.io.IOException;
43  import java.io.InputStream;
44  import java.io.OutputStream;
45  import java.util.ArrayList;
46  import java.util.Iterator;
47  import java.util.List;
48  import java.util.Properties;
49  
50  @Component( role = ArchetypeCreationConfigurator.class )
51  public class DefaultArchetypeCreationConfigurator
52      extends AbstractLogEnabled
53      implements ArchetypeCreationConfigurator
54  {
55      @Requirement
56      private ArchetypeCreationQueryer archetypeCreationQueryer;
57  
58      @Requirement
59      private ArchetypeFactory archetypeFactory;
60  
61      @Requirement
62      private ArchetypeFilesResolver archetypeFilesResolver;
63  
64      public Properties configureArchetypeCreation( MavenProject project, Boolean interactiveMode,
65                                                    Properties commandLineProperties, File propertyFile,
66                                                    List<String> languages )
67          throws IOException, ArchetypeNotDefined, ArchetypeNotConfigured, PrompterException, TemplateCreationException
68      {
69          Properties properties = initialiseArchetypeProperties( commandLineProperties, propertyFile );
70  
71          ArchetypeDefinition archetypeDefinition = archetypeFactory.createArchetypeDefinition( properties );
72  
73          if ( !archetypeDefinition.isDefined() )
74          {
75              archetypeDefinition = defineDefaultArchetype( project, properties );
76          }
77  
78          ArchetypeConfiguration archetypeConfiguration =
79              archetypeFactory.createArchetypeConfiguration( project, archetypeDefinition, properties );
80  
81          String resolvedPackage = archetypeFilesResolver.resolvePackage( project.getBasedir(), languages );
82  
83          if ( !archetypeConfiguration.isConfigured() )
84          {
85              archetypeConfiguration =
86                  defineDefaultConfiguration( project, archetypeDefinition, resolvedPackage, properties );
87          }
88  
89          if ( interactiveMode.booleanValue() )
90          {
91              getLogger().debug( "Entering interactive mode" );
92  
93              boolean confirmed = false;
94              while ( !confirmed )
95              {
96                  if ( !archetypeDefinition.isDefined() )// <editor-fold text="...">
97                  {
98                      getLogger().debug( "Archetype is yet not defined" );
99                      if ( !archetypeDefinition.isGroupDefined() )
100                     {
101                         getLogger().debug( "Asking for archetype's groupId" );
102                         archetypeDefinition.setGroupId( archetypeCreationQueryer.getArchetypeGroupId( project.getGroupId() ) );
103                     }
104                     if ( !archetypeDefinition.isArtifactDefined() )
105                     {
106                         getLogger().debug( "Asking for archetype's artifactId" );
107                         archetypeDefinition.setArtifactId( archetypeCreationQueryer.getArchetypeArtifactId( project.getArtifactId()
108                             + Constants.ARCHETYPE_SUFFIX ) );
109                     }
110                     if ( !archetypeDefinition.isVersionDefined() )
111                     {
112                         getLogger().debug( "Asking for archetype's version" );
113                         archetypeDefinition.setVersion( archetypeCreationQueryer.getArchetypeVersion( project.getVersion() ) );
114                     }
115 
116                     archetypeFactory.updateArchetypeConfiguration( archetypeConfiguration, archetypeDefinition );
117                 } // </editor-fold>
118 
119                 if ( !archetypeConfiguration.isConfigured() )// <editor-fold text="...">
120                 {
121                     getLogger().debug( "Archetype is not yet configured" );
122                     if ( !archetypeConfiguration.isConfigured( Constants.GROUP_ID ) )
123                     {
124                         getLogger().debug( "Asking for project's groupId" );
125                         archetypeConfiguration.setProperty(
126                                                             Constants.GROUP_ID,
127                                                             archetypeCreationQueryer.getGroupId( archetypeConfiguration.getDefaultValue( Constants.GROUP_ID ) ) );
128                     }
129                     if ( !archetypeConfiguration.isConfigured( Constants.ARTIFACT_ID ) )
130                     {
131                         getLogger().debug( "Asking for project's artifactId" );
132                         archetypeConfiguration.setProperty(
133                                                             Constants.ARTIFACT_ID,
134                                                             archetypeCreationQueryer.getArtifactId( archetypeConfiguration.getDefaultValue( Constants.ARTIFACT_ID ) ) );
135                     }
136                     if ( !archetypeConfiguration.isConfigured( Constants.VERSION ) )
137                     {
138                         getLogger().debug( "Asking for project's version" );
139                         archetypeConfiguration.setProperty(
140                                                             Constants.VERSION,
141                                                             archetypeCreationQueryer.getVersion( archetypeConfiguration.getDefaultValue( Constants.VERSION ) ) );
142                     }
143                     if ( !archetypeConfiguration.isConfigured( Constants.PACKAGE ) )
144                     {
145                         getLogger().debug( "Asking for project's package" );
146                         archetypeConfiguration.setProperty(
147                                                             Constants.PACKAGE,
148                                                             archetypeCreationQueryer.getPackage( StringUtils.isEmpty( resolvedPackage ) ? archetypeConfiguration.getDefaultValue( Constants.PACKAGE )
149                                                                             : resolvedPackage ) );
150                     }
151                 } // </editor-fold>
152 
153                 boolean stopAddingProperties = false;
154                 while ( !stopAddingProperties )
155                 {
156                     getLogger().debug( "Asking for another required property" );
157                     stopAddingProperties = !archetypeCreationQueryer.askAddAnotherProperty();
158 
159                     if ( !stopAddingProperties )
160                     {
161                         getLogger().debug( "Asking for required property key" );
162 
163                         String propertyKey = archetypeCreationQueryer.askNewPropertyKey();
164                         getLogger().debug( "Asking for required property value" );
165 
166                         String replacementValue =
167                             archetypeCreationQueryer.askReplacementValue(
168                                                                           propertyKey,
169                                                                           archetypeConfiguration.getDefaultValue( propertyKey ) );
170                         archetypeConfiguration.setDefaultProperty( propertyKey, replacementValue );
171                         archetypeConfiguration.setProperty( propertyKey, replacementValue );
172                     }
173                 }
174 
175                 getLogger().debug( "Asking for configuration confirmation" );
176                 if ( archetypeCreationQueryer.confirmConfiguration( archetypeConfiguration ) )
177                 {
178                     confirmed = true;
179                 }
180                 else
181                 {
182                     getLogger().debug( "Reseting archetype's definition and configuration" );
183                     archetypeConfiguration.reset();
184                     archetypeDefinition.reset();
185                 }
186             } // end while
187         }
188         else
189         {
190             getLogger().debug( "Entering batch mode" );
191             if ( !archetypeDefinition.isDefined() )
192             {
193                 throw new ArchetypeNotDefined( "The archetype is not defined" );
194             }
195             else if ( !archetypeConfiguration.isConfigured() )
196             {
197                 throw new ArchetypeNotConfigured( "The archetype is not configured", null );
198             }
199         } // end if
200 
201         return archetypeConfiguration.toProperties();
202     }
203 
204     private ArchetypeDefinition defineDefaultArchetype( MavenProject project, Properties properties )
205     {
206         if ( StringUtils.isEmpty( properties.getProperty( Constants.ARCHETYPE_GROUP_ID ) ) )
207         {
208             properties.setProperty( Constants.ARCHETYPE_GROUP_ID, project.getGroupId() );
209         }
210         if ( StringUtils.isEmpty( properties.getProperty( Constants.ARCHETYPE_ARTIFACT_ID ) ) )
211         {
212             properties.setProperty( Constants.ARCHETYPE_ARTIFACT_ID, project.getArtifactId()
213                 + Constants.ARCHETYPE_SUFFIX );
214         }
215         if ( StringUtils.isEmpty( properties.getProperty( Constants.ARCHETYPE_VERSION ) ) )
216         {
217             properties.setProperty( Constants.ARCHETYPE_VERSION, project.getVersion() );
218         }
219 
220         return archetypeFactory.createArchetypeDefinition( properties );
221     }
222 
223     private ArchetypeConfiguration defineDefaultConfiguration( MavenProject project,
224                                                                ArchetypeDefinition archetypeDefinition,
225                                                                String resolvedPackage, Properties properties )
226     {
227         if ( StringUtils.isEmpty( properties.getProperty( Constants.GROUP_ID ) ) )
228         {
229             getLogger().info( "Setting default groupId: " + project.getGroupId() );
230             properties.setProperty( Constants.GROUP_ID, project.getGroupId() );
231         }
232 
233         if ( StringUtils.isEmpty( properties.getProperty( Constants.ARTIFACT_ID ) ) )
234         {
235             getLogger().info( "Setting default artifactId: " + project.getArtifactId() );
236             properties.setProperty( Constants.ARTIFACT_ID, project.getArtifactId() );
237         }
238 
239         if ( StringUtils.isEmpty( properties.getProperty( Constants.VERSION ) ) )
240         {
241             getLogger().info( "Setting default version: " + project.getVersion() );
242             properties.setProperty( Constants.VERSION, project.getVersion() );
243         }
244 
245         if ( StringUtils.isEmpty( properties.getProperty( Constants.ARCHETYPE_GROUP_ID ) ) )
246         {
247             getLogger().info( "Setting default archetype's groupId: " + project.getGroupId() );
248             properties.setProperty( Constants.ARCHETYPE_GROUP_ID, project.getGroupId() );
249         }
250 
251         if ( StringUtils.isEmpty( properties.getProperty( Constants.ARCHETYPE_ARTIFACT_ID ) ) )
252         {
253             getLogger().info( "Setting default archetype's artifactId: " + project.getArtifactId() );
254             properties.setProperty( Constants.ARCHETYPE_ARTIFACT_ID, project.getArtifactId()
255                 + Constants.ARCHETYPE_SUFFIX );
256         }
257 
258         if ( StringUtils.isEmpty( properties.getProperty( Constants.ARCHETYPE_VERSION ) ) )
259         {
260             getLogger().info( "Setting default archetype's version: " + project.getVersion() );
261             properties.setProperty( Constants.ARCHETYPE_VERSION, project.getVersion() );
262         }
263 
264         if ( StringUtils.isEmpty( properties.getProperty( Constants.PACKAGE /*, properties.getProperty ( Constants.PACKAGE_NAME ) */ ) ) )
265         {
266             if ( StringUtils.isEmpty( resolvedPackage ) )
267             {
268                 resolvedPackage = project.getGroupId();
269             }
270             getLogger().info( "Setting default package: " + resolvedPackage );
271             /* properties.setProperty ( Constants.PACKAGE_NAME, resolvedPackage ); */
272             properties.setProperty( Constants.PACKAGE, resolvedPackage );
273         }
274 
275         return archetypeFactory.createArchetypeConfiguration( project, archetypeDefinition, properties );
276     }
277 
278     public void readProperties( Properties properties, File propertyFile )
279         throws IOException
280     {
281         getLogger().debug( "Reading property file " + propertyFile );
282 
283         InputStream is = new FileInputStream( propertyFile );
284 
285         try
286         {
287             properties.load( is );
288 
289             getLogger().debug( "Read " + properties.size() + " properties" );
290         }
291         finally
292         {
293             IOUtil.close( is );
294         }
295     }
296 
297     public void writeProperties( Properties properties, File propertyFile )
298         throws IOException
299     {
300         Properties storedProperties = new Properties();
301         try
302         {
303             readProperties( storedProperties, propertyFile );
304         }
305         catch ( FileNotFoundException ex )
306         {
307             getLogger().debug( "Property file not found. Creating a new one" );
308         }
309 
310         getLogger().debug( "Adding " + properties.size() + " properties" );
311 
312         Iterator<?> propertiesIterator = properties.keySet().iterator();
313         while ( propertiesIterator.hasNext() )
314         {
315             String propertyKey = (String) propertiesIterator.next();
316             storedProperties.setProperty( propertyKey, properties.getProperty( propertyKey ) );
317         }
318 
319         OutputStream os = new FileOutputStream( propertyFile );
320 
321         try
322         {
323             storedProperties.store( os, "" );
324 
325             getLogger().debug( "Stored " + storedProperties.size() + " properties" );
326         }
327         finally
328         {
329             IOUtil.close( os );
330         }
331     }
332 
333     private Properties initialiseArchetypeProperties( Properties commandLineProperties, File propertyFile )
334         throws IOException
335     {
336         Properties properties = new Properties();
337 
338         if ( propertyFile != null )
339         {
340             try
341             {
342                 readProperties( properties, propertyFile );
343             }
344             catch ( FileNotFoundException ex )
345             {
346                 getLogger().debug( "archetype.properties does not exist" );
347             }
348         }
349 
350         return properties;
351     }
352 
353     private Properties removeDottedProperties( Properties properties )
354     {
355         List<String> toRemove = new ArrayList<String>( 0 );
356 
357         for ( Iterator<?> keys = properties.keySet().iterator(); keys.hasNext(); )
358         {
359             String key = (String) keys.next();
360             if ( key.indexOf( "." ) >= 0 )
361             {
362                 toRemove.add( key );
363             }
364         }
365 
366         for ( String key : toRemove )
367         {
368             properties.remove( key );
369         }
370         return properties;
371     }
372 }