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.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
49 public class DefaultArchetypeCreationConfigurator
50 extends AbstractLogEnabled
51 implements ArchetypeCreationConfigurator
52 {
53
54 private ArchetypeCreationQueryer archetypeCreationQueryer;
55
56
57 private ArchetypeFactory archetypeFactory;
58
59
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() )
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 }
116
117 if ( !archetypeConfiguration.isConfigured() )
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 }
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 }
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 }
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
263 {
264 if ( StringUtils.isEmpty( resolvedPackage ) )
265 {
266 resolvedPackage = project.getGroupId();
267 }
268 getLogger().info( "Setting default package: " + resolvedPackage );
269
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 }