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; } }