blob: ccd24a41a05bf5f2d5766e3060417945d3ae151a [file] [log] [blame]
package org.apache.maven.continuum.core.action;
/*
* 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.maven.continuum.ContinuumException;
import org.apache.maven.continuum.execution.maven.m2.SettingsConfigurationException;
import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
import org.apache.maven.continuum.model.project.Project;
import org.apache.maven.continuum.project.builder.ContinuumProjectBuilder;
import org.apache.maven.continuum.project.builder.ContinuumProjectBuilderException;
import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
import org.apache.maven.continuum.project.builder.manager.ContinuumProjectBuilderManager;
import org.apache.maven.continuum.project.builder.manager.ContinuumProjectBuilderManagerException;
import org.apache.maven.continuum.utils.ContinuumUrlValidator;
import org.apache.maven.continuum.utils.URLUserInfo;
import org.apache.maven.settings.MavenSettingsBuilder;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Map;
/**
* Resolve the project url being passed in and gather authentication information
* if the url is so configured, then create the projects
* <p/>
* Supports:
* <p/>
* - standard maven-scm url
* - MungedUrl https://username:password@host
* - maven settings based, server = host and scm info set to username and password
*
* @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
* @version $Id$
* @plexus.component role="org.codehaus.plexus.action.Action"
* role-hint="create-projects-from-metadata"
*/
public class CreateProjectsFromMetadataAction
extends AbstractContinuumAction
{
/**
* Metadata url for adding projects.
*/
private static final String KEY_URL = "url";
private static final String KEY_PROJECT_BUILDER_ID = "builderId";
private static final String KEY_PROJECT_BUILDING_RESULT = "projectBuildingResult";
private static final String KEY_LOAD_RECURSIVE_PROJECTS = "loadRecursiveProjects";
public static final String KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY = "checkoutProjectsInSingleDirectory";
/**
* @plexus.requirement
*/
private ContinuumProjectBuilderManager projectBuilderManager;
/**
* @plexus.requirement
*/
private MavenSettingsBuilder mavenSettingsBuilder;
/**
* @plexus.requirement role-hint="continuumUrl"
*/
private ContinuumUrlValidator urlValidator;
public void execute( Map context )
throws ContinuumException, ContinuumProjectBuilderManagerException, ContinuumProjectBuilderException
{
String projectBuilderId = getProjectBuilderId( context );
boolean loadRecursiveProjects = isLoadRecursiveProject( context );
boolean checkoutProjectsInSingleDirectory = getBoolean( context, KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY );
int projectGroupId = getProjectGroupId( context );
String curl = getUrl( context );
URL url;
ContinuumProjectBuilder projectBuilder = projectBuilderManager.getProjectBuilder( projectBuilderId );
ContinuumProjectBuildingResult result;
try
{
BuildDefinitionTemplate buildDefinitionTemplate = getBuildDefinitionTemplate( context );
if ( buildDefinitionTemplate == null )
{
buildDefinitionTemplate = projectBuilder.getDefaultBuildDefinitionTemplate();
}
if ( !curl.startsWith( "http" ) )
{
url = new URL( curl );
result = projectBuilder.buildProjectsFromMetadata( url, null, null, loadRecursiveProjects,
buildDefinitionTemplate,
checkoutProjectsInSingleDirectory, projectGroupId );
}
else
{
url = new URL( curl );
String username = null;
String password = null;
try
{
Settings settings = getSettings();
getLogger().info( "checking for settings auth setup" );
if ( settings != null && settings.getServer( url.getHost() ) != null )
{
getLogger().info( "found setting based auth setup, using" );
Server server = settings.getServer( url.getHost() );
username = server.getUsername();
password = server.getPassword();
}
}
catch ( SettingsConfigurationException se )
{
getLogger().warn( "problem with settings file, disabling scm resolution of username and password" );
}
if ( username == null )
{
URLUserInfo urlUserInfo = urlValidator.extractURLUserInfo( curl );
username = urlUserInfo.getUsername();
password = urlUserInfo.getPassword();
}
if ( urlValidator.isValid( curl ) )
{
result = projectBuilder.buildProjectsFromMetadata( url, username, password, loadRecursiveProjects,
buildDefinitionTemplate,
checkoutProjectsInSingleDirectory,
projectGroupId );
}
else
{
result = new ContinuumProjectBuildingResult();
getLogger().info( "Malformed URL (MungedHttpsURL is not valid): " + hidePasswordInUrl( curl ) );
result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
}
}
if ( result.getProjects() != null )
{
String scmRootUrl = getScmRootUrl( result.getProjects() );
if ( scmRootUrl == null || scmRootUrl.equals( "" ) )
{
if ( curl.indexOf( "pom.xml" ) > 0 )
{
scmRootUrl = curl.substring( 0, curl.indexOf( "pom.xml" ) - 1 );
}
else
{
scmRootUrl = curl;
}
}
//setUrl( context, scmRootUrl );
setProjectScmRootUrl( context, scmRootUrl );
}
}
catch ( MalformedURLException e )
{
getLogger().info( "Malformed URL: " + hidePasswordInUrl( curl ), e );
result = new ContinuumProjectBuildingResult();
result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
}
catch ( URISyntaxException e )
{
getLogger().info( "Malformed URL: " + hidePasswordInUrl( curl ), e );
result = new ContinuumProjectBuildingResult();
result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
}
setProjectBuildingResult( context, result );
}
private String hidePasswordInUrl( String url )
{
int indexAt = url.indexOf( "@" );
if ( indexAt < 0 )
{
return url;
}
String s = url.substring( 0, indexAt );
int pos = s.lastIndexOf( ":" );
return s.substring( 0, pos + 1 ) + "*****" + url.substring( indexAt );
}
private Settings getSettings()
throws SettingsConfigurationException
{
try
{
return mavenSettingsBuilder.buildSettings();
}
catch ( IOException e )
{
throw new SettingsConfigurationException( "Error reading settings file", e );
}
catch ( XmlPullParserException e )
{
throw new SettingsConfigurationException( e.getMessage(), e.getDetail(), e.getLineNumber(),
e.getColumnNumber() );
}
}
private String getScmRootUrl( List<Project> projects )
{
String scmRootUrl = "";
for ( Project project : projects )
{
String scmUrl = project.getScmUrl();
scmRootUrl = getCommonPath( scmUrl, scmRootUrl );
}
return scmRootUrl;
}
private String getCommonPath( String path1, String path2 )
{
if ( path2 == null || path2.equals( "" ) )
{
return path1;
}
else
{
int indexDiff = StringUtils.differenceAt( path1, path2 );
String commonPath = path1.substring( 0, indexDiff );
if ( commonPath.lastIndexOf( '/' ) != commonPath.length() - 1 && !( path1.contains( new String(
commonPath + "/" ) ) || path2.contains( new String( commonPath + "/" ) ) ) )
{
while ( commonPath.lastIndexOf( '/' ) != commonPath.length() - 1 )
{
commonPath = commonPath.substring( 0, commonPath.length() - 1 );
}
}
return commonPath;
}
}
public ContinuumProjectBuilderManager getProjectBuilderManager()
{
return projectBuilderManager;
}
public void setProjectBuilderManager( ContinuumProjectBuilderManager projectBuilderManager )
{
this.projectBuilderManager = projectBuilderManager;
}
public MavenSettingsBuilder getMavenSettingsBuilder()
{
return mavenSettingsBuilder;
}
public void setMavenSettingsBuilder( MavenSettingsBuilder mavenSettingsBuilder )
{
this.mavenSettingsBuilder = mavenSettingsBuilder;
}
public ContinuumUrlValidator getUrlValidator()
{
return urlValidator;
}
public void setUrlValidator( ContinuumUrlValidator urlValidator )
{
this.urlValidator = urlValidator;
}
public static String getUrl( Map<String, Object> context )
{
return getString( context, KEY_URL );
}
public static void setUrl( Map<String, Object> context, String url )
{
context.put( KEY_URL, url );
}
public static String getProjectBuilderId( Map<String, Object> context )
{
return getString( context, KEY_PROJECT_BUILDER_ID );
}
public static void setProjectBuilderId( Map<String, Object> context, String projectBuilderId )
{
context.put( KEY_PROJECT_BUILDER_ID, projectBuilderId );
}
public static ContinuumProjectBuildingResult getProjectBuildingResult( Map<String, Object> context )
{
return (ContinuumProjectBuildingResult) getObject( context, KEY_PROJECT_BUILDING_RESULT );
}
private static void setProjectBuildingResult( Map<String, Object> context, ContinuumProjectBuildingResult result )
{
context.put( KEY_PROJECT_BUILDING_RESULT, result );
}
public static boolean isLoadRecursiveProject( Map<String, Object> context )
{
return getBoolean( context, KEY_LOAD_RECURSIVE_PROJECTS );
}
public static void setLoadRecursiveProject( Map<String, Object> context, boolean loadRecursiveProject )
{
context.put( KEY_LOAD_RECURSIVE_PROJECTS, loadRecursiveProject );
}
public static boolean isCheckoutProjectsInSingleDirectory( Map<String, Object> context )
{
return getBoolean( context, KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY );
}
public static void setCheckoutProjectsInSingleDirectory( Map<String, Object> context,
boolean checkoutProjectsInSingleDirectory )
{
context.put( KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY, checkoutProjectsInSingleDirectory );
}
}