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.commons.lang.StringUtils;
23 import org.apache.maven.archetype.ArchetypeGenerationRequest;
24 import org.apache.maven.archetype.ArchetypeManager;
25 import org.apache.maven.archetype.catalog.Archetype;
26 import org.apache.maven.archetype.exception.ArchetypeNotDefined;
27 import org.apache.maven.archetype.exception.ArchetypeSelectionFailure;
28 import org.apache.maven.archetype.exception.UnknownArchetype;
29 import org.apache.maven.archetype.exception.UnknownGroup;
30 import org.apache.maven.archetype.ui.ArchetypeDefinition;
31 import org.apache.maven.project.ProjectBuildingRequest;
32 import org.codehaus.plexus.component.annotations.Component;
33 import org.codehaus.plexus.component.annotations.Requirement;
34 import org.codehaus.plexus.components.interactivity.PrompterException;
35 import org.codehaus.plexus.logging.AbstractLogEnabled;
36
37 import java.io.IOException;
38 import java.util.HashMap;
39 import java.util.LinkedHashMap;
40 import java.util.List;
41 import java.util.Map;
42
43 @Component( role = ArchetypeSelector.class, hint = "default" )
44 public class DefaultArchetypeSelector
45 extends AbstractLogEnabled
46 implements ArchetypeSelector
47 {
48 static final String DEFAULT_ARCHETYPE_GROUPID = "org.apache.maven.archetypes";
49
50 static final String DEFAULT_ARCHETYPE_VERSION = "1.0";
51
52 static final String DEFAULT_ARCHETYPE_ARTIFACTID = "maven-archetype-quickstart";
53
54 @Requirement
55 private ArchetypeSelectionQueryer archetypeSelectionQueryer;
56
57 @Requirement
58 private ArchetypeManager archetypeManager;
59
60 public void selectArchetype( ArchetypeGenerationRequest request, Boolean interactiveMode, String catalogs )
61 throws ArchetypeNotDefined, UnknownArchetype, UnknownGroup, IOException, PrompterException,
62 ArchetypeSelectionFailure
63 {
64 ArchetypeDefinition definition = new ArchetypeDefinition( request );
65
66 if ( definition.isDefined() && StringUtils.isNotEmpty( request.getArchetypeRepository() ) )
67 {
68 getLogger().info( "Archetype defined by properties" );
69 return;
70 }
71
72 Map<String, List<Archetype>> archetypes = getArchetypesByCatalog( request.getProjectBuildingRequest(), catalogs );
73
74 if ( StringUtils.isNotBlank( request.getFilter() ) )
75 {
76
77 archetypes = ArchetypeSelectorUtils.getFilteredArchetypesByCatalog( archetypes, request.getFilter() );
78 if ( archetypes.isEmpty() )
79 {
80 getLogger().info( "Your filter doesn't match any archetype, so try again with another value." );
81 return;
82 }
83 }
84
85 if ( definition.isDefined() )
86 {
87 Map.Entry<String, Archetype> found =
88 findArchetype( archetypes, request.getArchetypeGroupId(), request.getArchetypeArtifactId() );
89
90 if ( found != null )
91 {
92 String catalogKey = found.getKey();
93 Archetype archetype = found.getValue();
94
95 updateRepository( definition, archetype );
96
97 getLogger().info( "Archetype repository not defined. Using the one from " + archetype + " found in catalog "
98 + catalogKey );
99 }
100 else
101 {
102 getLogger().warn(
103 "Archetype not found in any catalog. Falling back to central repository (http://repo.maven.apache.org/maven2)." );
104 getLogger().warn(
105 "Use -DarchetypeRepository=<your repository> if archetype's repository is elsewhere." );
106
107 definition.setRepository( "http://repo.maven.apache.org/maven2" );
108 }
109 }
110 else if ( definition.isPartiallyDefined() )
111 {
112 Map.Entry<String, Archetype> found =
113 findArchetype( archetypes, request.getArchetypeGroupId(), request.getArchetypeArtifactId() );
114
115 if ( found != null )
116 {
117 String catalogKey = found.getKey();
118 Archetype archetype = found.getValue();
119
120 updateDefinition( definition, archetype );
121
122 getLogger().info( "Archetype " + archetype + " found in catalog " + catalogKey );
123 }
124 else
125 {
126 getLogger().warn( "Specified archetype not found." );
127 if ( interactiveMode.booleanValue() )
128 {
129 definition.setVersion( null );
130 definition.setGroupId( null );
131 definition.setArtifactId( null );
132 }
133 }
134 }
135
136
137 if ( definition.getGroupId() == null )
138 {
139 definition.setGroupId( DEFAULT_ARCHETYPE_GROUPID );
140 }
141 if ( definition.getVersion() == null )
142 {
143 definition.setVersion( DEFAULT_ARCHETYPE_VERSION );
144 }
145
146 if ( !definition.isPartiallyDefined() )
147 {
148
149 if ( definition.getArtifactId() == null )
150 {
151 getLogger().info(
152 "No archetype defined. Using " + DEFAULT_ARCHETYPE_ARTIFACTID + " (" + definition.getGroupId() + ":"
153 + DEFAULT_ARCHETYPE_ARTIFACTID + ":" + definition.getVersion() + ")" );
154 definition.setArtifactId( DEFAULT_ARCHETYPE_ARTIFACTID );
155 }
156
157 if ( interactiveMode.booleanValue() && ( archetypes.size() > 0 ) )
158 {
159 Archetype selectedArchetype = archetypeSelectionQueryer.selectArchetype( archetypes, definition );
160
161 updateDefinition( definition, selectedArchetype );
162 }
163
164
165
166 if ( !definition.isPartiallyDefined() )
167 {
168 throw new ArchetypeSelectionFailure( "No valid archetypes could be found to choose." );
169 }
170 }
171
172
173 definition.updateRequest( request );
174 }
175
176
177 private Map<String, List<Archetype>> getArchetypesByCatalog( ProjectBuildingRequest buildingRequest, String catalogs )
178 {
179 if ( catalogs == null )
180 {
181 throw new NullPointerException( "Catalogs cannot be null" );
182 }
183
184 Map<String, List<Archetype>> archetypes = new LinkedHashMap<String, List<Archetype>>();
185
186 for ( String catalog : StringUtils.split( catalogs, "," ) )
187 {
188 if ( "internal".equalsIgnoreCase( catalog ) )
189 {
190 archetypes.put( "internal", archetypeManager.getInternalCatalog().getArchetypes() );
191 }
192 else if ( "local".equalsIgnoreCase( catalog ) )
193 {
194 archetypes.put( "local", archetypeManager.getLocalCatalog( buildingRequest ).getArchetypes() );
195 }
196 else if ( "remote".equalsIgnoreCase( catalog ) )
197 {
198 List<Archetype> archetypesFromRemote =
199 archetypeManager.getRemoteCatalog( buildingRequest ).getArchetypes();
200
201 if ( archetypesFromRemote.size() > 0 )
202 {
203 archetypes.put( "remote", archetypesFromRemote );
204 }
205 else
206 {
207 getLogger().warn( "No archetype found in remote catalog. Defaulting to internal catalog" );
208 archetypes.put( "internal", archetypeManager.getInternalCatalog().getArchetypes() );
209 }
210 }
211 }
212
213 if ( archetypes.size() == 0 )
214 {
215 getLogger().info( "No catalog defined. Using internal catalog" );
216
217 archetypes.put( "internal", archetypeManager.getInternalCatalog().getArchetypes() );
218 }
219 return archetypes;
220 }
221
222 private void updateRepository( ArchetypeDefinition definition, Archetype archetype )
223 {
224 String repository = archetype.getRepository();
225 if ( StringUtils.isNotEmpty( repository ) )
226 {
227 definition.setRepository( repository );
228 }
229 }
230
231 private void updateDefinition( ArchetypeDefinition definition, Archetype archetype )
232 {
233 definition.setGroupId( archetype.getGroupId() );
234 definition.setArtifactId( archetype.getArtifactId() );
235 definition.setVersion( archetype.getVersion() );
236 definition.setName( archetype.getArtifactId() );
237 updateRepository( definition, archetype );
238 definition.setGoals( StringUtils.join( archetype.getGoals().iterator(), "," ) );
239 }
240
241 public void setArchetypeSelectionQueryer( ArchetypeSelectionQueryer archetypeSelectionQueryer )
242 {
243 this.archetypeSelectionQueryer = archetypeSelectionQueryer;
244 }
245
246 private Map.Entry<String, Archetype> findArchetype( Map<String, List<Archetype>> archetypes, String groupId,
247 String artifactId )
248 {
249 Archetype example = new Archetype();
250 example.setGroupId( groupId );
251 example.setArtifactId( artifactId );
252
253 for ( Map.Entry<String, List<Archetype>> entry : archetypes.entrySet() )
254 {
255 List<Archetype> catalog = entry.getValue();
256
257 if ( catalog.contains( example ) )
258 {
259 Archetype archetype = catalog.get( catalog.indexOf( example ) );
260
261 return newMapEntry( entry.getKey(), archetype );
262 }
263 }
264
265 return null;
266 }
267
268 private static <K, V> Map.Entry<K, V> newMapEntry( K key, V value )
269 {
270 Map<K, V> map = new HashMap<K, V>( 1 );
271 map.put( key, value );
272
273 return map.entrySet().iterator().next();
274 }
275 }