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