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