blob: 37f1db2503010531d735c81c9393d19ec6d569dc [file] [log] [blame]
package org.apache.maven.continuum.notification.wagon;
/*
* 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.artifact.manager.WagonManager;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.DefaultArtifactRepository;
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
import org.apache.maven.continuum.ContinuumException;
import org.apache.maven.continuum.configuration.ConfigurationException;
import org.apache.maven.continuum.configuration.ConfigurationService;
import org.apache.maven.continuum.model.project.BuildDefinition;
import org.apache.maven.continuum.model.project.BuildResult;
import org.apache.maven.continuum.model.project.Project;
import org.apache.maven.continuum.model.project.ProjectNotifier;
import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
import org.apache.maven.continuum.notification.MessageContext;
import org.apache.maven.continuum.notification.NotificationException;
import org.apache.maven.model.DistributionManagement;
import org.apache.maven.model.Site;
import org.apache.maven.profiles.DefaultProfileManager;
import org.apache.maven.profiles.ProfileManager;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.settings.MavenSettingsBuilder;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.wagon.CommandExecutionException;
import org.apache.maven.wagon.CommandExecutor;
import org.apache.maven.wagon.ConnectionException;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.TransferFailedException;
import org.apache.maven.wagon.UnsupportedProtocolException;
import org.apache.maven.wagon.Wagon;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authentication.AuthenticationInfo;
import org.apache.maven.wagon.authorization.AuthorizationException;
import org.apache.maven.wagon.observers.Debug;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.apache.maven.wagon.repository.Repository;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
/**
* @author <a href="mailto:hisidro@exist.com">Henry Isidro</a>
* @author <a href="mailto:nramirez@exist.com">Napoleon Esmundo C. Ramirez</a>
*/
@Service( "notifier#wagon" )
public class WagonContinuumNotifier
extends AbstractContinuumNotifier
implements Contextualizable
{
public static final String BUILD_OUTPUT_FILE_NAME = "buildresult.txt";
private static final Logger log = LoggerFactory.getLogger( WagonContinuumNotifier.class );
@Resource
private ConfigurationService configurationService;
@Resource
private WagonManager wagonManager;
@Resource
private MavenProjectBuilder projectBuilder;
@Resource
private MavenSettingsBuilder settingsBuilder;
/**
* @plexus.configuration
*/
private String localRepository;
private Settings settings;
private ProfileManager profileManager;
private PlexusContainer container;
public String getType()
{
return "wagon";
}
public void sendMessage( String messageId, MessageContext context )
throws NotificationException
{
Project project = context.getProject();
List<ProjectNotifier> notifiers = context.getNotifiers();
BuildResult build = context.getBuildResult();
BuildDefinition buildDefinition = context.getBuildDefinition();
// ----------------------------------------------------------------------
// If there wasn't any building done, don't notify
// ----------------------------------------------------------------------
if ( build == null )
{
return;
}
// ----------------------------------------------------------------------
// Deloy build result to given url
// ----------------------------------------------------------------------
try
{
/*
* acquire the MavenProject associated to the Project in context
*/
MavenProject mavenProject = getMavenProject( project, buildDefinition );
if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_COMPLETE ) )
{
for ( ProjectNotifier notifier : notifiers )
{
buildComplete( notifier, build, mavenProject );
}
}
}
catch ( ContinuumException e )
{
throw new NotificationException( "Error while notifiying.", e );
}
}
private void buildComplete( ProjectNotifier notifier, BuildResult build, MavenProject mavenProject )
throws ContinuumException
{
String id;
String url;
Map<String, String> configuration = notifier.getConfiguration();
if ( configuration.containsKey( "url" ) )
{
url = configuration.get( "url" );
id = configuration.get( "id" );
}
else
{
DistributionManagement distributionManagement = mavenProject.getDistributionManagement();
if ( distributionManagement == null )
{
throw new ContinuumException( "Missing distribution management information in the project." );
}
Site site = distributionManagement.getSite();
if ( site == null )
{
throw new ContinuumException(
"Missing site information in the distribution management element in the project." );
}
url = site.getUrl();
id = site.getId();
}
if ( url == null )
{
throw new ContinuumException( "The URL to the site is not defined." );
}
Repository repository = new Repository( id, url );
Wagon wagon;
try
{
wagon = wagonManager.getWagon( repository.getProtocol() );
}
catch ( UnsupportedProtocolException e )
{
throw new ContinuumException( "Unsupported protocol: '" + repository.getProtocol() + "'", e );
}
if ( !wagon.supportsDirectoryCopy() )
{
throw new ContinuumException(
"Wagon protocol '" + repository.getProtocol() + "' doesn't support directory copying" );
}
try
{
if ( log.isDebugEnabled() )
{
Debug debug = new Debug();
wagon.addSessionListener( debug );
wagon.addTransferListener( debug );
}
ProxyInfo proxyInfo = getProxyInfo( repository );
if ( proxyInfo != null )
{
wagon.connect( repository, getAuthenticationInfo( id ), proxyInfo );
}
else
{
wagon.connect( repository, getAuthenticationInfo( id ) );
}
File buildOutputFile = configurationService.getBuildOutputFile( build.getId(), build.getProject().getId() );
wagon.put( buildOutputFile, BUILD_OUTPUT_FILE_NAME );
// TODO: current wagon uses zip which will use the umask on remote host instead of honouring our settings
// Force group writeable
if ( wagon instanceof CommandExecutor )
{
CommandExecutor exec = (CommandExecutor) wagon;
exec.executeCommand( "chmod -Rf g+w " + repository.getBasedir() );
}
}
catch ( ConfigurationException e )
{
throw new ContinuumException( "Error uploading build results to deployed site.", e );
}
catch ( ResourceDoesNotExistException e )
{
throw new ContinuumException( "Error uploading site", e );
}
catch ( TransferFailedException e )
{
throw new ContinuumException( "Error uploading site", e );
}
catch ( AuthorizationException e )
{
throw new ContinuumException( "Error uploading site", e );
}
catch ( ConnectionException e )
{
throw new ContinuumException( "Error uploading site", e );
}
catch ( AuthenticationException e )
{
throw new ContinuumException( "Error uploading site", e );
}
catch ( CommandExecutionException e )
{
throw new ContinuumException( "Error uploading site", e );
}
finally
{
try
{
wagon.disconnect();
}
catch ( ConnectionException e )
{
log.error( "Error disconnecting wagon - ignored", e );
}
}
}
private MavenProject getMavenProject( Project project, BuildDefinition buildDefinition )
throws ContinuumException
{
File projectWorkingDir = new File( configurationService.getWorkingDirectory(), Integer.toString(
project.getId() ) );
File pomFile = new File( projectWorkingDir, buildDefinition.getBuildFile() );
MavenProject mavenProject;
try
{
mavenProject = projectBuilder.build( pomFile, getLocalRepository(), getProfileManager() );
}
catch ( ProjectBuildingException e )
{
throw new ContinuumException( "Unable to acquire the MavenProject in " + pomFile.getAbsolutePath(), e );
}
return mavenProject;
}
private Settings getSettings()
{
if ( settings == null )
{
try
{
settings = settingsBuilder.buildSettings();
}
catch ( IOException e )
{
log.error( "Failed to get Settings", e );
}
catch ( XmlPullParserException e )
{
log.error( "Failed to get Settings", e );
}
}
return settings;
}
private ArtifactRepository getLocalRepository()
{
String repo = localRepository;
if ( getSettings() != null && !StringUtils.isEmpty( getSettings().getLocalRepository() ) )
{
repo = getSettings().getLocalRepository();
}
return new DefaultArtifactRepository( "local-repository", "file://" + repo, new DefaultRepositoryLayout() );
}
private ProfileManager getProfileManager()
{
if ( profileManager == null )
{
profileManager = new DefaultProfileManager( container, getSettings() );
}
return profileManager;
}
public void contextualize( Context context )
throws ContextException
{
container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
}
private ProxyInfo getProxyInfo( Repository repository )
{
Settings settings = getSettings();
if ( settings.getProxies() != null && !settings.getProxies().isEmpty() )
{
for ( Proxy p : (List<Proxy>) settings.getProxies() )
{
wagonManager.addProxy( p.getProtocol(), p.getHost(), p.getPort(), p.getUsername(), p.getPassword(),
p.getNonProxyHosts() );
}
}
return wagonManager.getProxy( repository.getProtocol() );
}
private AuthenticationInfo getAuthenticationInfo( String repositoryId )
{
Settings settings = getSettings();
Server server = settings.getServer( repositoryId );
if ( server == null )
{
return null;
}
wagonManager.addAuthenticationInfo( repositoryId, server.getUsername(), server.getPassword(),
server.getPrivateKey(), server.getPassphrase() );
return wagonManager.getAuthenticationInfo( repositoryId );
}
}