1 package org.apache.maven.archetype.ui.creation;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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() )
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 }
118
119 if ( !archetypeConfiguration.isConfigured() )
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 }
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 }
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 }
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
265 {
266 if ( StringUtils.isEmpty( resolvedPackage ) )
267 {
268 resolvedPackage = project.getGroupId();
269 }
270 getLogger().info( "Setting default package: " + resolvedPackage );
271
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 }