1 package org.apache.maven.archetype.ui.generation;
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.ArchetypeGenerationRequest;
23 import org.apache.maven.archetype.common.ArchetypeArtifactManager;
24 import org.apache.maven.archetype.common.ArchetypeRegistryManager;
25 import org.apache.maven.archetype.common.Constants;
26 import org.apache.maven.archetype.exception.ArchetypeGenerationConfigurationFailure;
27 import org.apache.maven.archetype.exception.ArchetypeNotConfigured;
28 import org.apache.maven.archetype.exception.ArchetypeNotDefined;
29 import org.apache.maven.archetype.exception.UnknownArchetype;
30 import org.apache.maven.archetype.old.OldArchetype;
31 import org.apache.maven.archetype.ui.ArchetypeConfiguration;
32 import org.apache.maven.archetype.ui.ArchetypeDefinition;
33 import org.apache.maven.archetype.ui.ArchetypeFactory;
34 import org.apache.maven.artifact.repository.ArtifactRepository;
35 import org.apache.velocity.VelocityContext;
36 import org.apache.velocity.app.Velocity;
37 import org.apache.velocity.context.Context;
38 import org.codehaus.plexus.component.annotations.Component;
39 import org.codehaus.plexus.component.annotations.Requirement;
40 import org.codehaus.plexus.components.interactivity.PrompterException;
41 import org.codehaus.plexus.logging.AbstractLogEnabled;
42 import org.codehaus.plexus.util.IOUtil;
43 import org.codehaus.plexus.util.StringUtils;
44
45 import java.io.IOException;
46 import java.io.StringWriter;
47 import java.util.ArrayList;
48 import java.util.Collections;
49 import java.util.Comparator;
50 import java.util.List;
51 import java.util.Properties;
52
53
54 @Component( role = ArchetypeGenerationConfigurator.class, hint = "default" )
55 public class DefaultArchetypeGenerationConfigurator
56 extends AbstractLogEnabled
57 implements ArchetypeGenerationConfigurator
58 {
59 @Requirement
60 OldArchetype oldArchetype;
61
62 @Requirement
63 private ArchetypeArtifactManager archetypeArtifactManager;
64
65 @Requirement
66 private ArchetypeFactory archetypeFactory;
67
68 @Requirement
69 private ArchetypeGenerationQueryer archetypeGenerationQueryer;
70
71 @Requirement
72 private ArchetypeRegistryManager archetypeRegistryManager;
73
74 public void setArchetypeArtifactManager( ArchetypeArtifactManager archetypeArtifactManager )
75 {
76 this.archetypeArtifactManager = archetypeArtifactManager;
77 }
78
79 public void configureArchetype( ArchetypeGenerationRequest request, Boolean interactiveMode,
80 Properties executionProperties )
81 throws ArchetypeNotDefined, UnknownArchetype, ArchetypeNotConfigured, IOException, PrompterException,
82 ArchetypeGenerationConfigurationFailure
83 {
84 ArtifactRepository localRepository = request.getLocalRepository();
85
86 ArtifactRepository archetypeRepository = null;
87
88 List<ArtifactRepository> repositories = new ArrayList<ArtifactRepository>();
89
90 Properties properties = new Properties( executionProperties );
91
92 ArchetypeDefinition ad = new ArchetypeDefinition( request );
93
94 if ( !ad.isDefined() )
95 {
96 if ( !interactiveMode.booleanValue() )
97 {
98 throw new ArchetypeNotDefined( "No archetype was chosen" );
99 }
100 else
101 {
102 throw new ArchetypeNotDefined( "The archetype is not defined" );
103 }
104 }
105 if ( request.getArchetypeRepository() != null )
106 {
107 archetypeRepository = archetypeRegistryManager.createRepository( request.getArchetypeRepository(),
108 ad.getArtifactId() + "-repo" );
109 repositories.add( archetypeRepository );
110 }
111 if ( request.getRemoteArtifactRepositories() != null )
112 {
113 repositories.addAll( request.getRemoteArtifactRepositories() );
114 }
115
116 if ( !archetypeArtifactManager.exists( ad.getGroupId(), ad.getArtifactId(), ad.getVersion(),
117 archetypeRepository, localRepository, repositories ) )
118 {
119 throw new UnknownArchetype(
120 "The desired archetype does not exist (" + ad.getGroupId() + ":" + ad.getArtifactId() + ":"
121 + ad.getVersion() + ")" );
122 }
123
124 request.setArchetypeVersion( ad.getVersion() );
125
126 ArchetypeConfiguration archetypeConfiguration;
127
128 if ( archetypeArtifactManager.isFileSetArchetype( ad.getGroupId(), ad.getArtifactId(), ad.getVersion(),
129 archetypeRepository, localRepository, repositories ) )
130 {
131 org.apache.maven.archetype.metadata.ArchetypeDescriptor archetypeDescriptor =
132 archetypeArtifactManager.getFileSetArchetypeDescriptor( ad.getGroupId(), ad.getArtifactId(),
133 ad.getVersion(), archetypeRepository,
134 localRepository, repositories );
135
136 archetypeConfiguration = archetypeFactory.createArchetypeConfiguration( archetypeDescriptor, properties );
137 }
138 else if ( archetypeArtifactManager.isOldArchetype( ad.getGroupId(), ad.getArtifactId(), ad.getVersion(),
139 archetypeRepository, localRepository, repositories ) )
140 {
141 org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor archetypeDescriptor =
142 archetypeArtifactManager.getOldArchetypeDescriptor( ad.getGroupId(), ad.getArtifactId(),
143 ad.getVersion(), archetypeRepository,
144 localRepository, repositories );
145
146 archetypeConfiguration = archetypeFactory.createArchetypeConfiguration( archetypeDescriptor, properties );
147 }
148 else
149 {
150 throw new ArchetypeGenerationConfigurationFailure( "The defined artifact is not an archetype" );
151 }
152
153 if ( interactiveMode.booleanValue() )
154 {
155 boolean confirmed = false;
156 Context context = new VelocityContext();
157 context.put( Constants.GROUP_ID, ad.getGroupId() );
158 context.put( Constants.ARTIFACT_ID, ad.getArtifactId() );
159 context.put( Constants.VERSION, ad.getVersion() );
160 while ( !confirmed )
161 {
162 List<String> propertiesRequired = archetypeConfiguration.getRequiredProperties();
163 getLogger().debug( "Required properties before content sort: " + propertiesRequired );
164 Collections.sort( propertiesRequired, new RequiredPropertyComparator( archetypeConfiguration ) );
165 getLogger().debug( "Required properties after content sort: " + propertiesRequired );
166
167 if ( !archetypeConfiguration.isConfigured() )
168 {
169 for ( String requiredProperty : propertiesRequired )
170 {
171 if ( !archetypeConfiguration.isConfigured( requiredProperty ) )
172 {
173 if ( "package".equals( requiredProperty ) )
174 {
175
176
177
178 String packageDefault = archetypeConfiguration.getDefaultValue( requiredProperty );
179 packageDefault = ( null == packageDefault || "".equals( packageDefault ) )
180 ? archetypeConfiguration.getProperty( "groupId" )
181 : archetypeConfiguration.getDefaultValue( requiredProperty );
182
183 String value =
184 getTransitiveDefaultValue( packageDefault, archetypeConfiguration, requiredProperty,
185 context );
186
187 value = archetypeGenerationQueryer.getPropertyValue( requiredProperty, value );
188
189 archetypeConfiguration.setProperty( requiredProperty, value );
190
191 context.put( Constants.PACKAGE, value );
192 }
193 else
194 {
195 String value = archetypeConfiguration.getDefaultValue( requiredProperty );
196
197 value = getTransitiveDefaultValue( value, archetypeConfiguration, requiredProperty,
198 context );
199
200 value = archetypeGenerationQueryer.getPropertyValue( requiredProperty, value );
201
202 archetypeConfiguration.setProperty( requiredProperty, value );
203
204 context.put( requiredProperty, value );
205 }
206 }
207 else
208 {
209 getLogger().info(
210 "Using property: " + requiredProperty + " = " + archetypeConfiguration.getProperty(
211 requiredProperty ) );
212 archetypeConfiguration.setProperty( requiredProperty, archetypeConfiguration.getProperty(
213 requiredProperty ) );
214 }
215 }
216 }
217 else
218 {
219
220 for ( String requiredProperty : propertiesRequired )
221 {
222 getLogger().info(
223 "Using property: " + requiredProperty + " = " + archetypeConfiguration.getProperty(
224 requiredProperty ) );
225 }
226 }
227
228 if ( !archetypeConfiguration.isConfigured() )
229 {
230 getLogger().warn( "Archetype is not fully configured" );
231 }
232 else if ( !archetypeGenerationQueryer.confirmConfiguration( archetypeConfiguration ) )
233 {
234 getLogger().debug( "Archetype generation configuration not confirmed" );
235 archetypeConfiguration.reset();
236 restoreCommandLineProperties( archetypeConfiguration, executionProperties );
237 }
238 else
239 {
240 getLogger().debug( "Archetype generation configuration confirmed" );
241
242 confirmed = true;
243 }
244 }
245 }
246 else
247 {
248 if ( !archetypeConfiguration.isConfigured() )
249 {
250 for ( String requiredProperty : archetypeConfiguration.getRequiredProperties() )
251 {
252 if ( !archetypeConfiguration.isConfigured( requiredProperty ) && (
253 archetypeConfiguration.getDefaultValue( requiredProperty ) != null ) )
254 {
255 archetypeConfiguration.setProperty( requiredProperty, archetypeConfiguration.getDefaultValue(
256 requiredProperty ) );
257 }
258 }
259
260
261 if ( !archetypeConfiguration.isConfigured() )
262 {
263 StringBuffer exceptionMessage = new StringBuffer();
264 exceptionMessage.append( "Archetype " );
265 exceptionMessage.append( request.getArchetypeGroupId() );
266 exceptionMessage.append( ":" );
267 exceptionMessage.append( request.getArchetypeArtifactId() );
268 exceptionMessage.append( ":" );
269 exceptionMessage.append( request.getArchetypeVersion() );
270 exceptionMessage.append( " is not configured" );
271
272 List<String> missingProperties = new ArrayList<String>( 0 );
273 for ( String requiredProperty : archetypeConfiguration.getRequiredProperties() )
274 {
275 if ( !archetypeConfiguration.isConfigured( requiredProperty ) )
276 {
277 exceptionMessage.append( "\n\tProperty " );
278 exceptionMessage.append( requiredProperty );
279 missingProperties.add( requiredProperty );
280 exceptionMessage.append( " is missing." );
281 getLogger().warn( "Property " + requiredProperty + " is missing. Add -D" + requiredProperty
282 + "=someValue" );
283 }
284 }
285
286 throw new ArchetypeNotConfigured( exceptionMessage.toString(), missingProperties );
287 }
288 }
289 }
290
291 request.setGroupId( archetypeConfiguration.getProperty( Constants.GROUP_ID ) );
292
293 request.setArtifactId( archetypeConfiguration.getProperty( Constants.ARTIFACT_ID ) );
294
295 request.setVersion( archetypeConfiguration.getProperty( Constants.VERSION ) );
296
297 request.setPackage( archetypeConfiguration.getProperty( Constants.PACKAGE ) );
298
299 properties = archetypeConfiguration.getProperties();
300
301 request.setProperties( properties );
302 }
303
304 private String getTransitiveDefaultValue( String defaultValue, ArchetypeConfiguration archetypeConfiguration,
305 String requiredProperty, Context context )
306 {
307 String result = defaultValue;
308 if ( null == result )
309 {
310 return null;
311 }
312 for ( String property : archetypeConfiguration.getRequiredProperties() )
313 {
314 if ( result.indexOf( "${" + property + "}" ) >= 0 )
315 {
316
317 result = StringUtils.replace( result, "${" + property + "}",
318 archetypeConfiguration.getProperty( property ) );
319 }
320 }
321 if ( result.contains( "${" ) )
322 {
323 result = evaluateProperty( context, requiredProperty, defaultValue );
324 }
325 return result;
326 }
327
328
329 private String evaluateProperty( Context context, String property, String value )
330 {
331 StringWriter stringWriter = new StringWriter();
332 try
333 {
334 Velocity.evaluate( context, stringWriter, property, value );
335 return stringWriter.toString();
336 }
337 catch ( Exception ex )
338 {
339 return value;
340 }
341 finally
342 {
343 IOUtil.close( stringWriter );
344 }
345 }
346
347
348 private void restoreCommandLineProperties( ArchetypeConfiguration archetypeConfiguration,
349 Properties executionProperties )
350 {
351 getLogger().debug( "Restoring command line properties" );
352
353 for ( String property : archetypeConfiguration.getRequiredProperties() )
354 {
355 if ( executionProperties.containsKey( property ) )
356 {
357 archetypeConfiguration.setProperty( property, executionProperties.getProperty( property ) );
358 getLogger().debug( "Restored " + property + "=" + archetypeConfiguration.getProperty( property ) );
359 }
360 }
361 }
362
363 public static class RequiredPropertyComparator
364 implements Comparator<String>
365 {
366 private final ArchetypeConfiguration archetypeConfiguration;
367
368 public RequiredPropertyComparator( ArchetypeConfiguration archetypeConfiguration )
369 {
370 this.archetypeConfiguration = archetypeConfiguration;
371 }
372
373 public int compare( String left, String right )
374 {
375 String leftDefault = archetypeConfiguration.getDefaultValue( left );
376
377 if ( ( leftDefault != null ) && leftDefault.indexOf( "${" + right + "}" ) >= 0 )
378 {
379 return 1;
380 }
381
382 String rightDefault = archetypeConfiguration.getDefaultValue( right );
383
384 if ( ( rightDefault != null ) && rightDefault.indexOf( "${" + left + "}" ) >= 0 )
385 {
386 return -1;
387 }
388
389 return comparePropertyName( left, right );
390 }
391
392 private int comparePropertyName( String left, String right )
393 {
394 if ( "groupId".equals( left ) )
395 {
396 return -1;
397 }
398 if ( "groupId".equals( right ) )
399 {
400 return 1;
401 }
402 if ( "artifactId".equals( left ) )
403 {
404 return -1;
405 }
406 if ( "artifactId".equals( right ) )
407 {
408 return 1;
409 }
410 if ( "version".equals( left ) )
411 {
412 return -1;
413 }
414 if ( "version".equals( right ) )
415 {
416 return 1;
417 }
418 if ( "package".equals( left ) )
419 {
420 return -1;
421 }
422 if ( "package".equals( right ) )
423 {
424 return 1;
425 }
426 return left.compareTo( right );
427 }
428 }
429 }