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" );
240             }
241         } // end if
242 
243         return removeDottedProperties(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             getLogger().info( "Setting default archetype's groupId: " + project.getGroupId() );
254             properties.setProperty( Constants.ARCHETYPE_GROUP_ID, project.getGroupId() );
255         }
256         if ( StringUtils.isEmpty( properties.getProperty( Constants.ARCHETYPE_ARTIFACT_ID ) ) )
257         {
258             getLogger().info(
259                 "Setting default archetype's artifactId: " + project.getArtifactId()
260             );
261             properties.setProperty(
262                 Constants.ARCHETYPE_ARTIFACT_ID,
263                 project.getArtifactId() + "-archetype"
264             );
265         }
266         if ( StringUtils.isEmpty( properties.getProperty( Constants.ARCHETYPE_VERSION ) ) )
267         {
268             getLogger().info( "Setting default archetype's version: " + project.getVersion() );
269             properties.setProperty( Constants.ARCHETYPE_VERSION, project.getVersion() );
270         }
271 
272         return archetypeFactory.createArchetypeDefinition( properties );
273     }
274 
275     private ArchetypeConfiguration defineDefaultConfiguration(
276         MavenProject project,
277         ArchetypeDefinition archetypeDefinition,
278         String resolvedPackage,
279         Properties properties
280     )
281     {
282         if ( StringUtils.isEmpty( properties.getProperty( Constants.GROUP_ID ) ) )
283         {
284             getLogger().info( "Setting default groupId: " + project.getGroupId() );
285             properties.setProperty( Constants.GROUP_ID, project.getGroupId() );
286         }
287 
288         if ( StringUtils.isEmpty( properties.getProperty( Constants.ARTIFACT_ID ) ) )
289         {
290             getLogger().info( "Setting default artifactId: " + project.getArtifactId() );
291             properties.setProperty( Constants.ARTIFACT_ID, project.getArtifactId() );
292         }
293 
294         if ( StringUtils.isEmpty( properties.getProperty( Constants.VERSION ) ) )
295         {
296             getLogger().info( "Setting default version: " + project.getVersion() );
297             properties.setProperty( Constants.VERSION, project.getVersion() );
298         }
299 
300         if ( StringUtils.isEmpty(
301             properties.getProperty(
302                 Constants.PACKAGE/*,
303                     properties.getProperty ( Constants.PACKAGE_NAME )*/
304             )
305         )
306             )
307         {
308             if ( StringUtils.isEmpty( resolvedPackage ) )
309             {
310                 resolvedPackage = project.getGroupId();
311             }
312             getLogger().info( "Setting default package: " + resolvedPackage );
313             /*properties.setProperty ( Constants.PACKAGE_NAME, resolvedPackage );*/
314             properties.setProperty( Constants.PACKAGE, resolvedPackage );
315         }
316 
317         return
318             archetypeFactory.createArchetypeConfiguration(
319                 project,
320                 archetypeDefinition,
321                 properties
322             );
323     }
324 
325     public void readProperties( Properties properties,
326                                 File propertyFile )
327         throws
328         IOException
329     {
330         getLogger().debug( "Reading property file " + propertyFile );
331 
332         InputStream is = new FileInputStream( propertyFile );
333 
334         try
335         {
336             properties.load( is );
337 
338             getLogger().debug( "Read " + properties.size() + " properties" );
339         }
340         finally
341         {
342             IOUtil.close( is );
343         }
344     }
345 
346     public void writeProperties( Properties properties,
347                                  File propertyFile )
348         throws
349         IOException
350     {
351         Properties storedProperties = new Properties();
352         try
353         {
354             readProperties( storedProperties, propertyFile );
355         }
356         catch ( FileNotFoundException ex )
357         {
358             getLogger().debug( "Property file not found. Creating a new one" );
359         }
360 
361         getLogger().debug( "Adding " + properties.size() + " properties" );
362 
363         Iterator propertiesIterator = properties.keySet().iterator();
364         while ( propertiesIterator.hasNext() )
365         {
366             String propertyKey = (String) propertiesIterator.next();
367             storedProperties.setProperty( propertyKey, properties.getProperty( propertyKey ) );
368         }
369 
370         OutputStream os = new FileOutputStream( propertyFile );
371 
372         try
373         {
374             storedProperties.store( os, "" );
375 
376             getLogger().debug( "Stored " + storedProperties.size() + " properties" );
377         }
378         finally
379         {
380             IOUtil.close( os );
381         }
382     }
383     
384     private Properties initialiseArchetypeProperties(
385         Properties commandLineProperties,
386         File propertyFile
387     )
388         throws
389         IOException
390     {
391         Properties properties = new Properties();
392 
393         if ( propertyFile != null )
394         {
395             try
396             {
397                 readProperties( properties, propertyFile );
398             }
399             catch ( FileNotFoundException ex )
400             {
401                 getLogger().debug( "archetype.properties does not exist" );
402             }
403         }
404 
405         return properties;
406     }
407 
408     private Properties removeDottedProperties(Properties properties) {
409         List toRemove=new ArrayList(0);
410         Iterator keys = properties.keySet().iterator();
411         while (keys.hasNext())
412         {
413             String key = (String) keys.next();
414             if (key.indexOf(".")>=0)
415             {
416                 toRemove.add(key);
417             }
418         }
419         Iterator keysToRemove =toRemove.iterator();
420         while(keysToRemove.hasNext())
421         {
422             String key = (String) keysToRemove.next();
423             properties.remove(key);
424         }
425         return properties;
426             
427         
428     }
429 }