package org.buildforce.uploader;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.deployer.ArtifactDeployer;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadata;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.model.FileSet;
import org.apache.maven.model.Model;
import org.apache.maven.model.PatternSet;
import org.apache.maven.model.Resource;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.artifact.ProjectArtifactMetadata;
import org.buildforce.uploader.metadata.ArtifactMetaData;
import org.buildforce.uploader.metadata.ArtifactMetaDataBuilder;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.WriterFactory;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* Uploads a local artifact repository to a remote location.
* <p/>
* Please note: Part of this code is a rip off from the maven-deploy-plugin,
* therefore credits go to the original authors as well.
*
* @author <a href="mailto:carlspring@gmail.com">Martin Todorov</a>
* @author <a href="mailto:aramirez@apache.org">Allan Ramirez</a>
* @goal upload
* @requiresProject false
*/
public class UploaderMojo extends AbstractMojo
{
private static final String[] INCLUDES = { "**/**" };
private static final String INCLUDES_JARS = "**/*.jar";
private static final String INCLUDES_WARS = "**/*.war";
private static final String SNAPSHOT_JARS = "**/**SNAPSHOT**/**.jar";
private static final String SNAPSHOT_WARS = "**/**SNAPSHOT**/**.war";
/**
* The maven project.
*
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;
/**
* @parameter expression="${artifactRepositoryDirectory}" required="true"
*/
private String artifactRepositoryDirectory;
/**
* @parameter expression="${component.org.apache.maven.artifact.deployer.ArtifactDeployer}"
* @required
* @readonly
*/
private ArtifactDeployer deployer;
/**
* @parameter expression="${localRepository}" default="${maven.repo.local}"
*/
private ArtifactRepository localRepository;
/**
* Used only if the mode is "copy".
*
* @parameter expression="${localDeploymentRepository}" required="false"
*/
private String localDeploymentRepository;
/**
* Server Id to map on the <id> under <server> section of settings.xml
* In most cases, this parameter will be required for authentication.
*
* @parameter expression="${repositoryId}" default-value="remote-repository"
* @required
*/
private String repositoryId;
/**
* The type of remote repository layout to deploy to. Try <i>legacy</i> for
* a Maven 1.x-style repository layout.
*
* @parameter expression="${repositoryLayout}" default-value="default"
* @required
*/
private String repositoryLayout;
/**
* Map that contains the layouts
*
* @component role="org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout"
*/
private Map repositoryLayouts;
/**
* Component used to create an artifact
*
* @component
*/
private ArtifactFactory artifactFactory;
/**
* Component used to create a repository
*
* @component
*/
private ArtifactRepositoryFactory repositoryFactory;
/**
* URL where the artifact will be deployed. <br/>
* ie ( file:///m2-repo or scp://host.com/path/to/repo )
*
* @parameter expression="${url}"
* @required
*/
private String url;
/**
* release / snapshot
*
* @parameter expression="${policy}" required="true" default="release"
*/
private String policy;
/**
* deploy / copy
*
* @parameter expression="${mode}" required="true" default="deploy"
*/
private String mode;
/**
* @parameter expressions="${includes}"
*/
private PatternSet includes;
/**
* @parameter expressions="${excludes}"
*/
private PatternSet excludes;
@Override
public void execute() throws MojoExecutionException, MojoFailureException
{
System.out.println(new File(".").getAbsolutePath());
System.out.println("artifactRepositoryDirectory = " + artifactRepositoryDirectory);
String[] artifacts = findArtifacts(artifactRepositoryDirectory);
// TODO: Convert to debugs:
getLog().info(" [ Artifacts list start ] ");
for (final String filePath : artifacts)
{
getLog().info(" " +filePath);
}
getLog().info(" [ *Artifacts list end* ] ");
int i = 1;
for (final String filePath : artifacts)
{
getLog().debug(filePath);
getLog().info(" [ Deploying artifact ] ");
getLog().info(" --> " + filePath + " (" +i + "/" +artifacts.length +")");
if (mode.equals("deploy"))
{
ArtifactMetaDataBuilder artifactMetaDataBuilder = new ArtifactMetaDataBuilder();
ArtifactMetaData artifactMetaData = artifactMetaDataBuilder.buildMetaData(filePath);
deployArtifact(artifactMetaData);
}
else
{
copyArtifacts(filePath);
}
getLog().info(" [ Artifact deployed! ] ");
i++;
}
}
/**
* Copies given resources to the build directory.
*
* @param file
* @throws MojoExecutionException
*/
public void copyArtifacts(String file)
throws MojoExecutionException
{
// String[] includedFiles = findArtifacts(artifactRepositoryDirectory);
// for (Object includedFile : includedFiles)
{
// String destination = (String) includedFile;
String destination = file;
File source = new File(artifactRepositoryDirectory, destination);
File destinationFile = new File(localDeploymentRepository, destination);
if (!destinationFile.getParentFile().exists())
destinationFile.getParentFile().mkdirs();
try
{
FileUtils.copyFile(source, destinationFile);
}
catch (IOException e)
{
throw new MojoExecutionException("Error copying web resource " + source, e);
}
}
}
public void deployArtifact(ArtifactMetaData artifactMetaData)
throws MojoExecutionException, MojoFailureException
{
ArtifactRepositoryLayout layout = (ArtifactRepositoryLayout) repositoryLayouts.get(repositoryLayout);
ArtifactRepository deploymentRepository = repositoryFactory.createDeploymentArtifactRepository(repositoryId,
url,
layout,
false);
final File pomFile = generatePomFile(artifactMetaData);
try
{
// Create the artifact
Artifact artifact;
if (artifactMetaData.getClassifier().equals(""))
{
artifact = artifactFactory.createArtifact(artifactMetaData.getGroupId(),
artifactMetaData.getArtifactId(),
artifactMetaData.getVersion(),
"compile",
artifactMetaData.getPackaging());
}
else
{
artifact = artifactFactory.createArtifactWithClassifier(artifactMetaData.getGroupId(),
artifactMetaData.getArtifactId(),
artifactMetaData.getVersion(),
artifactMetaData.getPackaging(),
artifactMetaData.getClassifier());
}
artifact.setFile(new File(artifactRepositoryDirectory + File.separatorChar +artifactMetaData.getArtifactPathInRepository()));
// Deploy the POM
boolean isPomArtifact = "pom".equals(artifactMetaData.getPackaging());
if (!isPomArtifact)
{
ArtifactMetadata metadata = new ProjectArtifactMetadata(artifact, pomFile);
artifact.addMetadata(metadata);
}
try
{
if (isPomArtifact)
{
getDeployer().deploy(pomFile, artifact, deploymentRepository, getLocalRepository());
}
else
{
final File file = artifact.getFile();
if (file != null && !file.isDirectory())
{
getLog().info(" [ Deploying... ]");
getLog().info(" --> " +artifactMetaData.toString() +" <--");
if (!Boolean.parseBoolean(System.getProperty("skip.deployment")))
getDeployer().deploy(file, artifact, deploymentRepository, getLocalRepository());
getLog().info(" [ *Deployed!* ]");
}
else
{
String message = "The packaging for this project did not assign a file to the build artifact";
throw new MojoExecutionException(message);
}
}
}
catch (ArtifactDeploymentException e)
{
throw new MojoExecutionException(e.getMessage(), e);
}
}
finally
{
//noinspection ResultOfMethodCallIgnored
pomFile.delete();
}
}
private String[] findArtifacts(String path) throws MojoExecutionException
{
DirectoryScanner scanner = new DirectoryScanner();
FileSet fileSet = new FileSet();
fileSet.setDirectory(path);
if (policy.toLowerCase().equals("snapshot"))
{
prepareInclusionSet(fileSet);
// fileSet.addInclude(SNAPSHOT_JARS);
// fileSet.addInclude(SNAPSHOT_WARS);
prepareExclusionSet(fileSet);
}
else
{
prepareInclusionSet(fileSet);
prepareExclusionSet(fileSet);
fileSet.addExclude(SNAPSHOT_JARS);
fileSet.addExclude(SNAPSHOT_WARS);
}
// Include default artifact types:
// fileSet.addInclude(INCLUDES_JARS);
// fileSet.addInclude(INCLUDES_WARS);
File resourceDirectory = new File(fileSet.getDirectory());
String[] finalIncludes = new String[fileSet.getIncludes().size()];
String[] finalExcludes = new String[fileSet.getExcludes().size()];
finalIncludes = fileSet.getIncludes().toArray(finalIncludes);
finalExcludes = fileSet.getExcludes().toArray(finalExcludes);
System.out.println("Includes: " + Arrays.toString(finalIncludes));
System.out.println("Excludes: " + Arrays.toString(finalExcludes));
scanner.setBasedir(resourceDirectory);
scanner.setIncludes(finalIncludes);
if (fileSet.getExcludes() != null && !fileSet.getExcludes().isEmpty())
scanner.setExcludes(finalExcludes);
scanner.addDefaultExcludes();
scanner.scan();
return scanner.getIncludedFiles();
}
private void prepareInclusionSet(FileSet fileSet)
{
if (includes != null)
{
List<String> includesList = includes.getIncludes();
for (String inclusion : includesList)
{
fileSet.addInclude(inclusion);
}
}
prepareFileSet(fileSet, "artifact.inclusion.patterns", true);
}
private void prepareExclusionSet(FileSet fileSet)
{
if (excludes != null)
{
List<String> excludesList = excludes.getExcludes();
for (String exclusion : excludesList)
{
fileSet.addExclude(exclusion);
}
}
prepareFileSet(fileSet, "artifact.exclusion.patterns", false);
}
private void prepareFileSet(FileSet fileSet, String property, boolean isInclusion)
{
String patternProperty = System.getProperty(property);
if (patternProperty != null)
{
String[] patterns = patternProperty.split(",");
for (String pattern : patterns)
{
if (isInclusion)
fileSet.addInclude(pattern.trim());
else
fileSet.addExclude(pattern.trim());
}
}
}
private File generatePomFile(ArtifactMetaData artifactMetaData)
throws MojoExecutionException
{
Writer fw = null;
try
{
File tempFile = File.createTempFile("mvninstall", ".pom");
tempFile.deleteOnExit();
Model model = new Model();
model.setModelVersion("4.0.0");
model.setGroupId(artifactMetaData.getGroupId());
model.setArtifactId(artifactMetaData.getArtifactId());
model.setVersion(artifactMetaData.getVersion());
model.setPackaging(artifactMetaData.getPackaging());
// model.setDescription(description);
fw = WriterFactory.newXmlWriter(tempFile);
new MavenXpp3Writer().write(fw, model);
return tempFile;
}
catch (IOException e)
{
throw new MojoExecutionException("Error writing temporary pom file: " + e.getMessage(), e);
}
finally
{
IOUtil.close(fw);
}
}
public ArtifactDeployer getDeployer()
{
return deployer;
}
public void setDeployer(ArtifactDeployer deployer)
{
this.deployer = deployer;
}
public ArtifactRepository getLocalRepository()
{
return localRepository;
}
public void setLocalRepository(ArtifactRepository localRepository)
{
this.localRepository = localRepository;
}
}