blob: 0f748f0ff8e74d7d6ea44f8811e42acfe43e9bc1 [file] [log] [blame]
package org.apache.maven.archetype.ui.generation;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.commons.lang.StringUtils;
import org.apache.maven.archetype.ArchetypeGenerationRequest;
import org.apache.maven.archetype.ArchetypeManager;
import org.apache.maven.archetype.catalog.Archetype;
import org.apache.maven.archetype.exception.ArchetypeNotDefined;
import org.apache.maven.archetype.exception.ArchetypeSelectionFailure;
import org.apache.maven.archetype.exception.UnknownArchetype;
import org.apache.maven.archetype.exception.UnknownGroup;
import org.apache.maven.archetype.ui.ArchetypeDefinition;
import org.apache.maven.project.ProjectBuildingRequest;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.components.interactivity.PrompterException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Component( role = ArchetypeSelector.class, hint = "default" )
public class DefaultArchetypeSelector
extends AbstractLogEnabled
implements ArchetypeSelector
{
static final String DEFAULT_ARCHETYPE_GROUPID = "org.apache.maven.archetypes";
static final String DEFAULT_ARCHETYPE_VERSION = "1.0";
static final String DEFAULT_ARCHETYPE_ARTIFACTID = "maven-archetype-quickstart";
@Requirement
private ArchetypeSelectionQueryer archetypeSelectionQueryer;
@Requirement
private ArchetypeManager archetypeManager;
@Override
public void selectArchetype( ArchetypeGenerationRequest request, Boolean interactiveMode, String catalogs )
throws ArchetypeNotDefined, UnknownArchetype, UnknownGroup, IOException, PrompterException,
ArchetypeSelectionFailure
{
ArchetypeDefinition definition = new ArchetypeDefinition( request );
if ( definition.isDefined() && StringUtils.isNotEmpty( request.getArchetypeRepository() ) )
{
getLogger().info( "Archetype defined by properties" );
return;
}
Map<String, List<Archetype>> archetypes = getArchetypesByCatalog( request.getProjectBuildingRequest(), catalogs );
if ( StringUtils.isNotBlank( request.getFilter() ) )
{
// applying some filtering depending on filter parameter
archetypes = ArchetypeSelectorUtils.getFilteredArchetypesByCatalog( archetypes, request.getFilter() );
if ( archetypes.isEmpty() )
{
getLogger().info( "Your filter doesn't match any archetype, so try again with another value." );
return;
}
}
if ( definition.isDefined() )
{
Map.Entry<String, Archetype> found =
findArchetype( archetypes, request.getArchetypeGroupId(), request.getArchetypeArtifactId() );
if ( found != null )
{
String catalogKey = found.getKey();
Archetype archetype = found.getValue();
updateRepository( definition, archetype );
getLogger().info( "Archetype repository not defined. Using the one from " + archetype + " found in catalog "
+ catalogKey );
}
else
{
getLogger().warn(
"Archetype not found in any catalog. Falling back to central repository." );
getLogger().warn(
"Add a repository with id 'archetype' in your settings.xml if archetype's repository is elsewhere." );
}
}
else if ( definition.isPartiallyDefined() )
{
Map.Entry<String, Archetype> found =
findArchetype( archetypes, request.getArchetypeGroupId(), request.getArchetypeArtifactId() );
if ( found != null )
{
String catalogKey = found.getKey();
Archetype archetype = found.getValue();
updateDefinition( definition, archetype );
getLogger().info( "Archetype " + archetype + " found in catalog " + catalogKey );
}
else
{
getLogger().warn( "Specified archetype not found." );
if ( interactiveMode.booleanValue() )
{
definition.setVersion( null );
definition.setGroupId( null );
definition.setArtifactId( null );
}
}
}
// set the defaults - only group and version can be auto-defaulted
if ( definition.getGroupId() == null )
{
definition.setGroupId( DEFAULT_ARCHETYPE_GROUPID );
}
if ( definition.getVersion() == null )
{
definition.setVersion( DEFAULT_ARCHETYPE_VERSION );
}
if ( !definition.isPartiallyDefined() )
{
// if artifact ID is set to its default, we still prompt to confirm
if ( definition.getArtifactId() == null )
{
getLogger().info(
"No archetype defined. Using " + DEFAULT_ARCHETYPE_ARTIFACTID + " (" + definition.getGroupId() + ":"
+ DEFAULT_ARCHETYPE_ARTIFACTID + ":" + definition.getVersion() + ")" );
definition.setArtifactId( DEFAULT_ARCHETYPE_ARTIFACTID );
}
if ( interactiveMode.booleanValue() && ( archetypes.size() > 0 ) )
{
Archetype selectedArchetype = archetypeSelectionQueryer.selectArchetype( archetypes, definition );
updateDefinition( definition, selectedArchetype );
}
// Make sure the groupId and artifactId are valid, the version may just default to
// the latest release.
if ( !definition.isPartiallyDefined() )
{
throw new ArchetypeSelectionFailure( "No valid archetypes could be found to choose." );
}
}
// finally update the request with gathered information
definition.updateRequest( request );
}
private Map<String, List<Archetype>> getArchetypesByCatalog( ProjectBuildingRequest buildingRequest, String catalogs )
{
if ( catalogs == null )
{
throw new NullPointerException( "Catalogs cannot be null" );
}
Map<String, List<Archetype>> archetypes = new LinkedHashMap<>();
for ( String catalog : StringUtils.split( catalogs, "," ) )
{
if ( "internal".equalsIgnoreCase( catalog ) )
{
archetypes.put( "internal", archetypeManager.getInternalCatalog().getArchetypes() );
}
else if ( "local".equalsIgnoreCase( catalog ) )
{
archetypes.put( "local", archetypeManager.getLocalCatalog( buildingRequest ).getArchetypes() );
}
else if ( "remote".equalsIgnoreCase( catalog ) )
{
List<Archetype> archetypesFromRemote =
archetypeManager.getRemoteCatalog( buildingRequest ).getArchetypes();
if ( archetypesFromRemote.size() > 0 )
{
archetypes.put( "remote", archetypesFromRemote );
}
else
{
getLogger().warn( "No archetype found in remote catalog. Defaulting to internal catalog" );
archetypes.put( "internal", archetypeManager.getInternalCatalog().getArchetypes() );
}
}
else
{
throw new IllegalArgumentException( "archetypeCatalog '" + catalog + "' is not supported anymore. "
+ "Please read the plugin documentation for details." );
}
}
if ( archetypes.size() == 0 )
{
getLogger().info( "No catalog defined. Using internal catalog" );
archetypes.put( "internal", archetypeManager.getInternalCatalog().getArchetypes() );
}
return archetypes;
}
private void updateRepository( ArchetypeDefinition definition, Archetype archetype )
{
String repository = archetype.getRepository();
if ( StringUtils.isNotEmpty( repository ) )
{
definition.setRepository( repository );
}
}
private void updateDefinition( ArchetypeDefinition definition, Archetype archetype )
{
definition.setGroupId( archetype.getGroupId() );
definition.setArtifactId( archetype.getArtifactId() );
definition.setVersion( archetype.getVersion() );
definition.setName( archetype.getArtifactId() );
updateRepository( definition, archetype );
definition.setGoals( StringUtils.join( archetype.getGoals().iterator(), "," ) );
}
public void setArchetypeSelectionQueryer( ArchetypeSelectionQueryer archetypeSelectionQueryer )
{
this.archetypeSelectionQueryer = archetypeSelectionQueryer;
}
private Map.Entry<String, Archetype> findArchetype( Map<String, List<Archetype>> archetypes, String groupId,
String artifactId )
{
Archetype example = new Archetype();
example.setGroupId( groupId );
example.setArtifactId( artifactId );
for ( Map.Entry<String, List<Archetype>> entry : archetypes.entrySet() )
{
List<Archetype> catalog = entry.getValue();
if ( catalog.contains( example ) )
{
Archetype archetype = catalog.get( catalog.indexOf( example ) );
return newMapEntry( entry.getKey(), archetype );
}
}
return null;
}
private static <K, V> Map.Entry<K, V> newMapEntry( K key, V value )
{
Map<K, V> map = new HashMap<>( 1 );
map.put( key, value );
return map.entrySet().iterator().next();
}
}