blob: 7b21613e8376ee34114828de371f5d39796e0d60 [file] [log] [blame]
package org.apache.maven.plugins.repository;
/*
* 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.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.model.License;
import org.apache.maven.model.Model;
import org.apache.maven.model.Scm;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.archiver.Archiver;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.jar.JarArchiver;
import org.codehaus.plexus.components.interactivity.InputHandler;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.util.xml.XmlStreamReader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
/**
* Packs artifacts already available in a local repository in a bundle for an
* upload requests. It requires that the artifact has a POM in the local
* repository. It will check for mandatory elements, asking interactively for
* missing values. Can be used to generate bundles for third parties artifacts
* that have been manually added to the local repository.
*
* @since 2.1
*/
@Mojo( name = "bundle-pack", requiresProject = false )
public class BundlePackMojo
extends AbstractMojo
{
public static final String POM = "pom.xml";
/**
* Jar archiver.
*/
@Component( role = Archiver.class, hint = "jar" )
protected JarArchiver jarArchiver;
/**
* Artifact resolver.
*/
@Component
protected ArtifactResolver artifactResolver;
/**
* Artifact factory.
*/
@Component
protected ArtifactFactory artifactFactory;
/**
* Local maven repository.
*/
@Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
protected ArtifactRepository localRepository;
/**
*/
@Component
protected InputHandler inputHandler;
/**
* Directory where the upload-bundle will be created.
*/
@Parameter( defaultValue = "${basedir}", readonly = true )
protected String basedir;
/**
* GroupId for the artifact to create an upload bundle for.
*/
@Parameter( property = "groupId" )
protected String groupId;
/**
* ArtifactId for the artifact to create an upload bundle for.
*/
@Parameter( property = "artifactId" )
protected String artifactId;
/**
* Version for the artifact to create an upload bundle for.
*/
@Parameter( property = "version" )
protected String version;
/**
* Viewable URL for SCM connections, in cases where this isn't provided by the POM.
*/
@Parameter( property = "scmUrl" )
protected String scmUrl;
/**
* Read-only URL for SCM tool connections, in cases where this isn't provided by the POM.
* <br/>
* <b>NOTE:</b> This should be a standard maven-scm URL. See the
* <a href="http://maven.apache.org/scm/scm-url-format.html">format guidelines</a> for more
* information.
*/
@Parameter( property = "scmConnection" )
protected String scmConnection;
/**
*/
@Parameter( defaultValue = "${settings}", readonly = true, required = true )
protected Settings settings;
/**
* Disable validations to make sure bundle supports project materialization.
* <br/>
* <b>WARNING: This means your project will be MUCH harder to use.</b>
*/
@Parameter( property = "bundle.disableMaterialization", defaultValue = "false" )
private boolean disableMaterialization;
@SuppressWarnings( "unchecked" )
public void execute()
throws MojoExecutionException
{
readArtifactDataFromUser();
Artifact artifact = artifactFactory.createProjectArtifact( groupId, artifactId, version );
try
{
artifactResolver.resolve( artifact, Collections.EMPTY_LIST, localRepository );
}
catch ( ArtifactResolutionException e )
{
throw new MojoExecutionException( "Unable to resolve artifact " + artifact.getId(), e );
}
catch ( ArtifactNotFoundException e )
{
throw new MojoExecutionException( "Artifact " + artifact.getId() + " not found in local repository", e );
}
File pom = artifact.getFile();
File dir = pom.getParentFile();
Model model = readPom( pom );
boolean rewrite = false;
try
{
if ( model.getPackaging() == null )
{
model.setPackaging( "jar" );
rewrite = true;
}
if ( model.getName() == null )
{
getLog().info( "Project name is missing, please type the project name [" + artifactId + "]:" );
model.setName( inputHandler.readLine() );
if ( model.getName() == null )
{
model.setName( artifactId );
}
rewrite = true;
}
if ( model.getDescription() == null )
{
getLog().info( "Project description is missing, please type the project description:" );
model.setDescription( inputHandler.readLine() );
rewrite = true;
}
if ( model.getUrl() == null )
{
getLog().info( "Project URL is missing, please type the project URL:" );
model.setUrl( inputHandler.readLine() );
rewrite = true;
}
List<License> licenses = model.getLicenses();
if ( licenses.isEmpty() )
{
License license = new License();
getLog().info( "License name is missing, please type the license name:" );
license.setName( inputHandler.readLine() );
getLog().info( "License URL is missing, please type the license URL:" );
license.setUrl( inputHandler.readLine() );
licenses.add( license );
rewrite = true;
}
if ( disableMaterialization )
{
getLog().warn( "Validations to confirm support for project materialization have been DISABLED."
+ "\n\nYour project may not provide the POM elements necessary to allow "
+ "users to retrieve sources on-demand,"
+ "\nor to easily checkout your project in an IDE. "
+ "THIS CAN SERIOUSLY INCONVENIENCE YOUR USERS.\n\nContinue? [y/N]" );
try
{
if ( 'y' != inputHandler.readLine()
.toLowerCase()
.charAt( 0 ) )
{
disableMaterialization = false;
}
}
catch ( IOException e )
{
getLog().debug( "Error reading confirmation: " + e.getMessage(), e );
}
}
if ( !disableMaterialization )
{
Scm scm = model.getScm();
if ( scm == null )
{
scm = new Scm();
model.setScm( scm );
}
if ( scm.getUrl() == null )
{
if ( scmUrl != null )
{
scm.setUrl( scmUrl );
}
else
{
getLog().info( "SCM view URL is missing, please type the URL for the viewable SCM interface:" );
scm.setUrl( inputHandler.readLine() );
rewrite = true;
}
}
if ( scm.getConnection() == null )
{
if ( scmConnection != null )
{
scm.setConnection( scmConnection );
}
else
{
getLog().info( "SCM read-only connection URL is missing, please type the read-only SCM URL:" );
scm.setConnection( inputHandler.readLine() );
rewrite = true;
}
}
}
}
catch ( IOException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
try
{
if ( rewrite )
{
new MavenXpp3Writer().write( WriterFactory.newXmlWriter( pom ), model );
}
String finalName = null;
if ( model.getBuild() != null )
{
finalName = model.getBuild()
.getFinalName();
}
if ( finalName == null )
{
finalName = model.getArtifactId() + "-" + model.getVersion();
}
boolean batchMode = settings == null ? false : !settings.isInteractiveMode();
List<File> files = BundleUtils.selectProjectFiles( dir, inputHandler, finalName, pom, getLog(), batchMode );
File bundle = new File( basedir, finalName + "-bundle.jar" );
jarArchiver.addFile( pom, POM );
boolean artifactChecks = !"pom".equals( model.getPackaging() );
boolean sourcesFound = false;
boolean javadocsFound = false;
for ( File f : files )
{
if ( artifactChecks && f.getName()
.endsWith( finalName + "-sources.jar" ) )
{
sourcesFound = true;
}
else if ( artifactChecks && f.getName()
.equals( finalName + "-javadoc.jar" ) )
{
javadocsFound = true;
}
jarArchiver.addFile( f, f.getName() );
}
if ( artifactChecks && !sourcesFound )
{
getLog().warn( "Sources not included in upload bundle." );
}
if ( artifactChecks && !javadocsFound )
{
getLog().warn( "Javadoc not included in upload bundle." );
}
jarArchiver.setDestFile( bundle );
jarArchiver.createArchive();
}
catch ( IOException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
catch ( ArchiverException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
}
/**
* Read groupId, artifactId and version from the user on the command line,
* if they were not provided as parameters.
*
* @throws MojoExecutionException If the values can't be read
*/
private void readArtifactDataFromUser()
throws MojoExecutionException
{
try
{
if ( groupId == null )
{
getLog().info( "groupId? " );
groupId = inputHandler.readLine();
}
if ( artifactId == null )
{
getLog().info( "artifactId? " );
artifactId = inputHandler.readLine();
}
if ( version == null )
{
getLog().info( "version? " );
version = inputHandler.readLine();
}
}
catch ( IOException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
}
/**
* Read the POM file.
*
* @param pom The file to read
* @return A Maven Model
* @throws MojoExecutionException if something goes wrong when reading the file
*/
private Model readPom( File pom )
throws MojoExecutionException
{
Model model;
XmlStreamReader reader = null;
try
{
reader = ReaderFactory.newXmlReader( pom );
model = new MavenXpp3Reader().read( reader );
reader.close();
reader = null;
}
catch ( XmlPullParserException e )
{
throw new MojoExecutionException( "Unable to parse POM at " + pom.getAbsolutePath() + ": " + e.getMessage(),
e );
}
catch ( FileNotFoundException e )
{
throw new MojoExecutionException( "Unable to read POM at " + pom.getAbsolutePath() + ": " + e.getMessage(),
e );
}
catch ( IOException e )
{
throw new MojoExecutionException( "Unable to read POM at " + pom.getAbsolutePath() + ": " + e.getMessage(),
e );
}
finally
{
IOUtil.close( reader );
}
return model;
}
}