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.commons.collections.iterators.ArrayIterator;
23  import org.apache.maven.archetype.ArchetypeGenerationRequest;
24  import org.apache.maven.archetype.catalog.Archetype;
25  import org.apache.maven.archetype.common.ArchetypeDefinition;
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.codehaus.plexus.components.interactivity.PrompterException;
31  import org.codehaus.plexus.logging.AbstractLogEnabled;
32  import org.codehaus.plexus.util.StringUtils;
33  
34  import java.io.IOException;
35  import java.util.HashMap;
36  import java.util.Iterator;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.Properties;
40  
41  /** @plexus.component */
42  public class DefaultArchetypeSelector
43      extends AbstractLogEnabled
44      implements ArchetypeSelector
45  {
46      static final String DEFAULT_ARCHETYPE_GROUPID = "org.apache.maven.archetypes";
47  
48      static final String DEFAULT_ARCHETYPE_VERSION = "1.0";
49  
50      static final String DEFAULT_ARCHETYPE_ARTIFACTID = "maven-archetype-quickstart";
51  
52      /** @plexus.requirement */
53      private ArchetypeSelectionQueryer archetypeSelectionQueryer;
54      /** @plexus.requirement */
55      private org.apache.maven.archetype.Archetype archetype;
56  
57      public void selectArchetype( ArchetypeGenerationRequest request, 
58              Boolean interactiveMode, String catalogs )
59          throws
60          ArchetypeNotDefined,
61          UnknownArchetype,
62          UnknownGroup,
63          IOException,
64          PrompterException,
65          ArchetypeSelectionFailure                    
66      {
67          //This should be an internal class
68          ArchetypeDefinition definition = new ArchetypeDefinition();
69  
70          definition.setGroupId( request.getArchetypeGroupId() );
71          definition.setArtifactId( request.getArchetypeArtifactId() );
72          definition.setVersion( request.getArchetypeVersion() );
73          
74          Map archetypes = getArchetypesByCatalog ( catalogs );
75  
76          if ( definition.isDefined ()
77              && StringUtils.isNotEmpty ( request.getArchetypeRepository () )
78          )
79          {
80              getLogger ().info ( "Archetype defined by properties" );
81          }
82          else
83          {
84              if ( definition.isDefined ()
85                  && StringUtils.isEmpty ( request.getArchetypeRepository () )
86              )
87              {
88                  Iterator ca = new ArrayIterator ( StringUtils.split ( catalogs, "," ) );
89                  boolean found = false;
90                  while ( !found && ca.hasNext () )
91                  {
92                      String catalogKey = (String) ca.next ();
93                      List catalog = (List) archetypes.get ( catalogKey );
94                      Archetype example = new Archetype ();
95                      example.setGroupId ( request.getArchetypeGroupId () );
96                      example.setArtifactId ( request.getArchetypeArtifactId () );
97                      if ( catalog.contains ( example ) )
98                      {
99                          found = true;
100 
101                         Archetype foundArchetype =
102                             (Archetype) catalog.get ( catalog.indexOf ( example ) );
103                         definition.setName ( foundArchetype.getArtifactId () );
104                         definition.setRepository ( foundArchetype.getRepository () );
105 
106                         getLogger ().info (
107                             "Archetype repository missing. Using the one from " + foundArchetype
108                             + " found in catalog " + catalogKey
109                         );
110                     }
111                 }
112                 if ( !found )
113                 {
114                     getLogger ().warn ( "No archetype repository found. Falling back to central repository (http://repo1.maven.org/maven2). " );
115                     getLogger ().warn ( "Use -DarchetypeRepository=<your repository> if archetype's repository is elsewhere." );
116                     
117                     definition.setRepository("http://repo1.maven.org/maven2");
118                 }
119             }
120             if ( !definition.isDefined () && definition.isPartiallyDefined () )
121             {
122                 Iterator ca = new ArrayIterator ( StringUtils.split ( catalogs, "," ) );
123                 boolean found = false;
124                 while ( !found && ca.hasNext () )
125                 {
126                     String catalogKey = (String) ca.next ();
127                     List catalog = (List) archetypes.get ( catalogKey );
128                     Archetype example = new Archetype ();
129                     example.setGroupId ( request.getArchetypeGroupId () );
130                     example.setArtifactId ( request.getArchetypeArtifactId () );
131                     if ( catalog.contains ( example ) )
132                     {
133                         found = true;
134 
135                         Archetype foundArchetype =
136                             (Archetype) catalog.get ( catalog.indexOf ( example ) );
137                         definition.setGroupId ( foundArchetype.getGroupId () );
138                         definition.setArtifactId ( foundArchetype.getArtifactId () );
139                         definition.setVersion ( foundArchetype.getVersion () );
140                         definition.setName ( foundArchetype.getArtifactId () );
141                         definition.setRepository ( foundArchetype.getRepository () );
142 
143                         String goals =
144                             StringUtils.join ( foundArchetype.getGoals ().iterator (), "," );
145                         definition.setGoals ( goals );
146 
147                         getLogger ().info (
148                             "Archetype " + foundArchetype
149                             + " found in catalog " + catalogKey
150                         );
151                     }
152                 }
153                 if ( !found )
154                 {
155                     getLogger ().warn ( "Specified archetype not found." );
156                     if ( interactiveMode.booleanValue () )
157                     {
158                         definition.setVersion ( null );
159                         definition.setGroupId ( null );
160                         definition.setArtifactId ( null );
161                     }
162                 }
163             }
164         }
165 
166         // set the defaults - only group and version can be auto-defaulted
167         if ( definition.getGroupId() == null )
168         {
169             definition.setGroupId( DEFAULT_ARCHETYPE_GROUPID );
170         }
171         if ( definition.getVersion() == null )
172         {
173             definition.setVersion( DEFAULT_ARCHETYPE_VERSION );
174         }
175 
176         if ( !definition.isDefined() && !definition.isPartiallyDefined() )
177         {
178             // if artifact ID is set to it's default, we still prompt to confirm 
179             if ( definition.getArtifactId() == null )
180             {
181                 getLogger().info( "No archetype defined. Using " + DEFAULT_ARCHETYPE_ARTIFACTID + " ("
182                     + definition.getGroupId() + ":" + DEFAULT_ARCHETYPE_ARTIFACTID + ":" + definition.getVersion()
183                     + ")" );
184                 definition.setArtifactId( DEFAULT_ARCHETYPE_ARTIFACTID );
185             }
186 
187             if ( interactiveMode.booleanValue() )
188             {
189                 if ( archetypes.size() > 0 )
190                 {
191                     Archetype selectedArchetype = archetypeSelectionQueryer.selectArchetype( archetypes, definition );
192 
193                     definition.setGroupId( selectedArchetype.getGroupId() );
194                     definition.setArtifactId( selectedArchetype.getArtifactId() );
195                     definition.setVersion( selectedArchetype.getVersion() );
196                     definition.setName( selectedArchetype.getArtifactId() );
197                     definition.setRepository( selectedArchetype.getRepository() );
198                     String goals = StringUtils.join( selectedArchetype.getGoals().iterator(), "," );
199                     definition.setGoals( goals );
200                 }
201             }
202         }
203 
204         // Make sure the groupId and artifactId are valid, the version may just default to
205         // the latest release.
206 
207         if ( !definition.isPartiallyDefined() )
208         {
209             throw new ArchetypeSelectionFailure( "No valid archetypes could be found to choose." );
210         }
211 
212         request.setArchetypeGroupId( definition.getGroupId() );
213 
214         request.setArchetypeArtifactId( definition.getArtifactId() );
215 
216         request.setArchetypeVersion( definition.getVersion() );
217 
218         request.setArchetypeGoals( definition.getGoals() );
219 
220         request.setArchetypeName( definition.getName() );
221 
222         if (StringUtils.isNotEmpty(definition.getRepository())){
223             request.setArchetypeRepository( definition.getRepository() );
224         }
225     }
226 
227     private Map getArchetypesByCatalog(String catalogs) {
228         if ( catalogs == null )
229         {
230             throw new NullPointerException( "catalogs can not be null" );
231         }
232 
233         Map archetypes = new HashMap();
234 
235         Iterator ca = new ArrayIterator(StringUtils.split(catalogs, ","));
236         while (ca.hasNext()) {
237             String catalog = (String) ca.next();
238 
239             if ("internal".equalsIgnoreCase(catalog)) {
240                 archetypes.put("internal", archetype.getInternalCatalog().getArchetypes());
241             } else if ("local".equalsIgnoreCase(catalog)) {
242                 archetypes.put("local", archetype.getDefaultLocalCatalog().getArchetypes());
243             } else if ("remote".equalsIgnoreCase(catalog)) {
244                 archetypes.put("remote", archetype.getRemoteCatalog().getArchetypes());
245             } else if (catalog.startsWith("file://")) {
246                 String path = catalog.substring(7);
247                 archetypes.put("local", archetype.getLocalCatalog(path).getArchetypes());
248             } else if (catalog.startsWith("http://")) {
249                 archetypes.put("remote", archetype.getRemoteCatalog(catalog).getArchetypes());
250             }
251         }
252 
253         if (archetypes.size() == 0) {
254             getLogger().info("No catalog defined. Using internal catalog");
255 
256             archetypes.put("internal", archetype.getInternalCatalog().getArchetypes());
257         }
258         return archetypes;
259     }
260 
261     private Properties getArchetypeDataSourceProperties( String sourceRoleHint,
262                                                          Properties archetypeCatalogProperties )
263     {
264         Properties p = new Properties();
265 
266         for ( Iterator i = archetypeCatalogProperties.keySet().iterator(); i.hasNext(); )
267         {
268             String key = (String) i.next();
269 
270             if ( key.startsWith( sourceRoleHint ) )
271             {
272                 String k = key.substring( sourceRoleHint.length() + 1 );
273 
274                 p.setProperty( k, archetypeCatalogProperties.getProperty( key ) );
275             }
276         }
277 
278         return p;
279     }
280 
281     public void setArchetypeSelectionQueryer( ArchetypeSelectionQueryer archetypeSelectionQueryer )
282     {
283         this.archetypeSelectionQueryer = archetypeSelectionQueryer;
284     }
285 }