Coverage Report - org.apache.maven.archetype.ui.generation.DefaultArchetypeSelector
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultArchetypeSelector
53%
60/112
47%
33/70
6.125
 
 1  
 package org.apache.maven.archetype.ui.generation;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 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.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  
 
 36  
 import java.io.IOException;
 37  
 import java.util.HashMap;
 38  
 import java.util.LinkedHashMap;
 39  
 import java.util.List;
 40  
 import java.util.Map;
 41  
 
 42  
 @Component( role = ArchetypeSelector.class )
 43  10
 public class DefaultArchetypeSelector
 44  
     extends AbstractLogEnabled
 45  
     implements ArchetypeSelector
 46  
 {
 47  
     static final String DEFAULT_ARCHETYPE_GROUPID = "org.apache.maven.archetypes";
 48  
 
 49  
     static final String DEFAULT_ARCHETYPE_VERSION = "1.0";
 50  
 
 51  
     static final String DEFAULT_ARCHETYPE_ARTIFACTID = "maven-archetype-quickstart";
 52  
 
 53  
     @Requirement
 54  
     private ArchetypeSelectionQueryer archetypeSelectionQueryer;
 55  
 
 56  
     @Requirement
 57  
     private ArchetypeManager archetypeManager;
 58  
 
 59  
     public void selectArchetype( ArchetypeGenerationRequest request, Boolean interactiveMode, String catalogs )
 60  
         throws ArchetypeNotDefined, UnknownArchetype, UnknownGroup, IOException, PrompterException,
 61  
         ArchetypeSelectionFailure
 62  
     {
 63  10
         ArchetypeDefinition definition = new ArchetypeDefinition( request );
 64  
 
 65  10
         if ( definition.isDefined() && StringUtils.isNotEmpty( request.getArchetypeRepository() ) )
 66  
         {
 67  0
             getLogger().info( "Archetype defined by properties" );
 68  0
             return;
 69  
         }
 70  
 
 71  10
         Map<String, List<Archetype>> archetypes = getArchetypesByCatalog( catalogs );
 72  
 
 73  10
         if ( StringUtils.isNotBlank( request.getFilter() ) )
 74  
         {
 75  
             // applying some filtering depending on filter parameter
 76  0
             archetypes = ArchetypeSelectorUtils.getFilteredArchetypesByCatalog( archetypes, request.getFilter() );
 77  0
             if ( archetypes.isEmpty() )
 78  
             {
 79  0
                 getLogger().info( "Your filter doesn't match any archetype, so try again with another value." );
 80  0
                 return;
 81  
             }
 82  
         }
 83  
 
 84  10
         if ( definition.isDefined() && StringUtils.isEmpty( request.getArchetypeRepository() ) )
 85  
         {
 86  2
             Map.Entry<String, Archetype> found =
 87  
                 findArchetype( archetypes, request.getArchetypeGroupId(), request.getArchetypeArtifactId() );
 88  
 
 89  2
             if ( found != null )
 90  
             {
 91  0
                 String catalogKey = found.getKey();
 92  0
                 Archetype archetype = found.getValue();
 93  
 
 94  0
                 updateRepository( definition, archetype, catalogKey );
 95  
 
 96  0
                 getLogger().info( "Archetype repository missing. Using the one from " + archetype + " found in catalog "
 97  
                                       + catalogKey );
 98  0
             }
 99  
             else
 100  
             {
 101  2
                 getLogger().warn(
 102  
                     "Archetype not found in any catalog. Falling back to central repository (http://repo1.maven.org/maven2)." );
 103  2
                 getLogger().warn(
 104  
                     "Use -DarchetypeRepository=<your repository> if archetype's repository is elsewhere." );
 105  
 
 106  2
                 definition.setRepository( "http://repo1.maven.org/maven2" );
 107  
             }
 108  
         }
 109  
 
 110  10
         if ( !definition.isDefined() && definition.isPartiallyDefined() )
 111  
         {
 112  0
             Map.Entry<String, Archetype> found =
 113  
                 findArchetype( archetypes, request.getArchetypeGroupId(), request.getArchetypeArtifactId() );
 114  
 
 115  0
             if ( found != null )
 116  
             {
 117  0
                 String catalogKey = found.getKey();
 118  0
                 Archetype archetype = found.getValue();
 119  
 
 120  0
                 updateDefinition( definition, archetype, catalogKey );
 121  
 
 122  0
                 getLogger().info( "Archetype " + archetype + " found in catalog " + catalogKey );
 123  0
             }
 124  
             else
 125  
             {
 126  0
                 getLogger().warn( "Specified archetype not found." );
 127  0
                 if ( interactiveMode.booleanValue() )
 128  
                 {
 129  0
                     definition.setVersion( null );
 130  0
                     definition.setGroupId( null );
 131  0
                     definition.setArtifactId( null );
 132  
                 }
 133  
             }
 134  
         }
 135  
 
 136  
         // set the defaults - only group and version can be auto-defaulted
 137  10
         if ( definition.getGroupId() == null )
 138  
         {
 139  8
             definition.setGroupId( DEFAULT_ARCHETYPE_GROUPID );
 140  
         }
 141  10
         if ( definition.getVersion() == null )
 142  
         {
 143  8
             definition.setVersion( DEFAULT_ARCHETYPE_VERSION );
 144  
         }
 145  
 
 146  10
         if ( !definition.isPartiallyDefined() )
 147  
         {
 148  
             // if artifact ID is set to its default, we still prompt to confirm
 149  6
             if ( definition.getArtifactId() == null )
 150  
             {
 151  6
                 getLogger().info(
 152  
                     "No archetype defined. Using " + DEFAULT_ARCHETYPE_ARTIFACTID + " (" + definition.getGroupId() + ":"
 153  
                         + DEFAULT_ARCHETYPE_ARTIFACTID + ":" + definition.getVersion() + ")" );
 154  6
                 definition.setArtifactId( DEFAULT_ARCHETYPE_ARTIFACTID );
 155  
             }
 156  
 
 157  6
             if ( interactiveMode.booleanValue() && ( archetypes.size() > 0 ) )
 158  
             {
 159  4
                 Archetype selectedArchetype = archetypeSelectionQueryer.selectArchetype( archetypes, definition );
 160  
 
 161  4
                 String catalogKey = getCatalogKey( archetypes, selectedArchetype );
 162  
 
 163  4
                 updateDefinition( definition, selectedArchetype, catalogKey );
 164  
             }
 165  
 
 166  
             // Make sure the groupId and artifactId are valid, the version may just default to
 167  
             // the latest release.
 168  6
             if ( !definition.isPartiallyDefined() )
 169  
             {
 170  0
                 throw new ArchetypeSelectionFailure( "No valid archetypes could be found to choose." );
 171  
             }
 172  
         }
 173  
 
 174  
         // finally update the request with gathered information
 175  10
         definition.updateRequest( request );
 176  10
     }
 177  
 
 178  
 
 179  
     private Map<String, List<Archetype>> getArchetypesByCatalog( String catalogs )
 180  
     {
 181  10
         if ( catalogs == null )
 182  
         {
 183  0
             throw new NullPointerException( "catalogs cannot be null" );
 184  
         }
 185  
 
 186  10
         Map<String, List<Archetype>> archetypes = new LinkedHashMap<String, List<Archetype>>();
 187  
 
 188  10
         for ( String catalog : StringUtils.split( catalogs, "," ) )
 189  
         {
 190  0
             if ( "internal".equalsIgnoreCase( catalog ) )
 191  
             {
 192  0
                 archetypes.put( "internal", archetypeManager.getInternalCatalog().getArchetypes() );
 193  
             }
 194  0
             else if ( "local".equalsIgnoreCase( catalog ) )
 195  
             {
 196  0
                 archetypes.put( "local", archetypeManager.getDefaultLocalCatalog().getArchetypes() );
 197  
             }
 198  0
             else if ( "remote".equalsIgnoreCase( catalog ) )
 199  
             {
 200  0
                 List<Archetype> archetypesFromRemote = archetypeManager.getRemoteCatalog().getArchetypes();
 201  0
                 if ( archetypesFromRemote.size() > 0 )
 202  
                 {
 203  0
                     archetypes.put( "remote", archetypesFromRemote );
 204  
                 }
 205  
                 else
 206  
                 {
 207  0
                     getLogger().warn( "No archetype found in remote catalog. Defaulting to internal catalog" );
 208  0
                     archetypes.put( "internal", archetypeManager.getInternalCatalog().getArchetypes() );
 209  
                 }
 210  0
             }
 211  0
             else if ( catalog.startsWith( "file://" ) )
 212  
             {
 213  0
                 String path = catalog.substring( 7 );
 214  0
                 archetypes.put( catalog, archetypeManager.getLocalCatalog( path ).getArchetypes() );
 215  0
             }
 216  0
             else if ( catalog.startsWith( "http://" ) || catalog.startsWith( "https://" ) )
 217  
             {
 218  0
                 archetypes.put( catalog, archetypeManager.getRemoteCatalog( catalog ).getArchetypes() );
 219  
             }
 220  
         }
 221  
 
 222  10
         if ( archetypes.size() == 0 )
 223  
         {
 224  10
             getLogger().info( "No catalog defined. Using internal catalog" );
 225  
 
 226  10
             archetypes.put( "internal", archetypeManager.getInternalCatalog().getArchetypes() );
 227  
         }
 228  10
         return archetypes;
 229  
     }
 230  
 
 231  
     private void updateRepository( ArchetypeDefinition definition, Archetype archetype, String catalogKey )
 232  
     {
 233  4
         String repository = archetype.getRepository();
 234  4
         if ( StringUtils.isNotEmpty( repository ) )
 235  
         {
 236  0
             definition.setRepository( repository );
 237  
         }
 238  4
         else if ( catalogKey.indexOf( ':' ) > 1 )
 239  
         {
 240  
             // file: or http:
 241  0
             int lastIndex = catalogKey.lastIndexOf( '/' );
 242  0
             String catalogBase = catalogKey.substring( 0, ( lastIndex > 7 ? lastIndex : catalogKey.length() ) );
 243  0
             definition.setRepository( catalogBase );
 244  
         }
 245  4
     }
 246  
 
 247  
     private void updateDefinition( ArchetypeDefinition definition, Archetype archetype, String catalogKey )
 248  
     {
 249  4
         definition.setGroupId( archetype.getGroupId() );
 250  4
         definition.setArtifactId( archetype.getArtifactId() );
 251  4
         definition.setVersion( archetype.getVersion() );
 252  4
         definition.setName( archetype.getArtifactId() );
 253  4
         updateRepository( definition, archetype, catalogKey );
 254  4
         definition.setGoals( StringUtils.join( archetype.getGoals().iterator(), "," ) );
 255  4
     }
 256  
 
 257  
     public void setArchetypeSelectionQueryer( ArchetypeSelectionQueryer archetypeSelectionQueryer )
 258  
     {
 259  10
         this.archetypeSelectionQueryer = archetypeSelectionQueryer;
 260  10
     }
 261  
 
 262  
     private String getCatalogKey( Map<String, List<Archetype>> archetypes, Archetype selectedArchetype )
 263  
     {
 264  4
         for ( Map.Entry<String, List<Archetype>> entry : archetypes.entrySet() )
 265  
         {
 266  4
             List<Archetype> catalog = entry.getValue();
 267  
 
 268  4
             if ( catalog.contains( selectedArchetype ) )
 269  
             {
 270  0
                 return entry.getKey();
 271  
             }
 272  4
         }
 273  4
         return "";
 274  
     }
 275  
 
 276  
     private Map.Entry<String, Archetype> findArchetype( Map<String, List<Archetype>> archetypes, String groupId,
 277  
                                                         String artifactId )
 278  
     {
 279  2
         Archetype example = new Archetype();
 280  2
         example.setGroupId( groupId );
 281  2
         example.setArtifactId( artifactId );
 282  
 
 283  2
         for ( Map.Entry<String, List<Archetype>> entry : archetypes.entrySet() )
 284  
         {
 285  2
             List<Archetype> catalog = entry.getValue();
 286  
 
 287  2
             if ( catalog.contains( example ) )
 288  
             {
 289  0
                 Archetype archetype = catalog.get( catalog.indexOf( example ) );
 290  
 
 291  0
                 return newMapEntry( entry.getKey(), archetype );
 292  
             }
 293  2
         }
 294  
 
 295  2
         return null;
 296  
     }
 297  
 
 298  
     private static <K, V> Map.Entry<K, V> newMapEntry( K key, V value )
 299  
     {
 300  0
         Map<K, V> map = new HashMap<K, V>( 1 );
 301  0
         map.put( key, value );
 302  
 
 303  0
         return map.entrySet().iterator().next();
 304  
     }
 305  
 }