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