package org.ops4j.pax.construct.project;
/*
* Copyright 2007 Stuart McCulloch
*
* Licensed 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 java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.ops4j.pax.construct.archetype.AbstractPaxArchetypeMojo;
import org.ops4j.pax.construct.util.PomUtils;
import org.ops4j.pax.construct.util.PomUtils.Pom;
/**
* Updates a Pax-Construct project or (when run in the scripts directory) the installed scripts to the latest version
*
* <code><pre>
* mvn pax:update [-Dversion=...]
* </pre></code>
*
* @goal update
* @aggregator true
*
* @requiresProject false
*/
public class UpdateMojo extends AbstractMojo
{
/**
* Component factory for Maven artifacts
*
* @component
*/
private ArtifactFactory m_factory;
/**
* Component for resolving Maven artifacts
*
* @component
*/
private ArtifactResolver m_resolver;
/**
* Component for resolving Maven metadata
*
* @component
*/
private ArtifactMetadataSource m_source;
/**
* List of remote Maven repositories for the containing project.
*
* @parameter expression="${project.remoteArtifactRepositories}"
* @required
* @readonly
*/
private List m_remoteRepos;
/**
* The local Maven repository for the containing project.
*
* @parameter expression="${localRepository}"
* @required
* @readonly
*/
private ArtifactRepository m_localRepo;
/**
* The directory containing the POM to be updated.
*
* @parameter expression="${targetDirectory}" default-value="${project.basedir}"
*/
private File targetDirectory;
/**
* The version of Pax-Construct to update to.
*
* @parameter expression="${version}"
*/
private String version;
/**
* {@inheritDoc}
*/
public void execute()
throws MojoExecutionException
{
String groupId = AbstractPaxArchetypeMojo.PAX_CONSTRUCT_GROUP_ID;
// find latest release if no explicit version is given
Artifact scripts = m_factory.createBuildArtifact( groupId, "scripts", version, "zip" );
if( PomUtils.needReleaseVersion( version ) )
{
version = PomUtils.getReleaseVersion( scripts, m_source, m_remoteRepos, m_localRepo, null );
scripts.selectVersion( version );
}
if( new File( targetDirectory, "pax-bootstrap-pom.xml" ).exists() )
{
updatePaxConstructScripts( scripts );
}
else if( new File( targetDirectory, "pom.xml" ).exists() )
{
updatePaxConstructProject();
}
else
{
getLog().warn( "pax-update should be run from the scripts directory, or from a Pax-Construct project" );
}
}
/**
* Update each script in turn from the zipfile stored in the repository
*
* @param scripts maven artifact pointing to the scripts
* @throws MojoExecutionException
*/
private void updatePaxConstructScripts( Artifact scripts )
throws MojoExecutionException
{
// download to local repository if not already there
if( !PomUtils.downloadFile( scripts, m_resolver, m_remoteRepos, m_localRepo ) )
{
throw new MojoExecutionException( "Unable to download scripts " + scripts );
}
getLog().info( "Updating scripts to version " + version );
try
{
ZipFile zip = new ZipFile( scripts.getFile() );
for( Enumeration i = zip.entries(); i.hasMoreElements(); )
{
ZipEntry entry = (ZipEntry) i.nextElement();
// only need shallow copying (no nested folders)
String name = new File( entry.getName() ).getName();
String path = new File( targetDirectory, name ).getPath();
if( !entry.isDirectory() )
{
// overwrite using data stored in the zip
InputStream in = zip.getInputStream( entry );
String data = IOUtil.toString( in );
FileUtils.fileWrite( path, data );
getLog().info( " => " + path );
}
}
}
catch( IOException e )
{
throw new MojoExecutionException( "Problem updating local scripts", e );
}
}
/**
* Update existing Pax-Construct project to use the latest release of the plugin
*
* @throws MojoExecutionException
*/
private void updatePaxConstructProject()
throws MojoExecutionException
{
try
{
// only need to update in one place...
Pom pom = PomUtils.readPom( targetDirectory );
boolean foundPlugin = pom.updatePluginVersion( "org.ops4j", "maven-pax-plugin", version );
if( foundPlugin )
{
getLog().info( "Updating Pax-Construct project to version " + version );
pom.write();
getLog().info( " => " + pom.getFile() );
}
else
{
getLog().warn( "Unable to find reference to org.ops4j:maven-pax-plugin" );
getLog().warn( "you may need to convert this project using 'pax-clone'" );
}
}
catch( IOException e )
{
throw new MojoExecutionException( "Problem reading Maven POM: " + targetDirectory );
}
}
}