package hudson.plugins.stagingrelease;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
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.DefaultArtifactRepository;
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.stage.RepositoryCopier;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.artifact.ProjectArtifactMetadata;
import org.apache.maven.settings.Settings;
import org.apache.maven.shared.release.ReleaseExecutionException;
import org.apache.maven.shared.release.ReleaseFailureException;
import org.apache.maven.shared.release.ReleaseResult;
import org.apache.maven.shared.release.config.ReleaseDescriptor;
import org.apache.maven.shared.release.phase.AbstractReleasePhase;
import org.apache.maven.wagon.WagonException;
import org.apache.maven.wagon.repository.Repository;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
* @plexus.component role="org.apache.maven.shared.release.phase.ReleasePhase"
* role-hint="deploy-repository"
* @author awpyv
*
*/
public class DeployRepositoryPhase extends AbstractReleasePhase {
private ArtifactRepository localRepository;
private ArtifactRepository stagingRepository;
private ArtifactRepository deploymentRepository;
/**
* @plexus.requirement
*/
private RepositoryCopier repositoryCopier;
/**
* @todo replace this with a real deployment that also works remote.
*/
public ReleaseResult execute(ReleaseDescriptor releaseDescriptor,
Settings settings, List reactorProjects)
throws ReleaseExecutionException, ReleaseFailureException {
ReleaseResult result = new ReleaseResult();
if (!releaseDescriptor.isDeploy()) {
result.setResultCode(ReleaseResult.UNDEFINED);
return result;
}
try {
if (releaseDescriptor.getDeploymentRepository().contains("scp:")) {
deployRemote(releaseDescriptor);
} else {
deployLocal(releaseDescriptor);
}
result.setResultCode(ReleaseResult.SUCCESS);
} catch (Exception e) {
e.printStackTrace();
logError(result, "Error while releasing.");
result.setResultCode(ReleaseResult.ERROR);
throw new ReleaseExecutionException("Error while releasing", e);
}
return result;
}
private void deployRemote(ReleaseDescriptor releaseDescriptor)
throws MojoFailureException, WagonException, IOException {
String version = (String) releaseDescriptor.getReleaseVersions()
.values().iterator().next();
DefaultArtifactRepository deploymentRepository = RepositoryUtil
.createRepository(releaseDescriptor.getDeploymentRepository());
DefaultArtifactRepository stagingRepository = RepositoryUtil
.createRepository(releaseDescriptor
.getTempDeploymentRepository());
repositoryCopier.copy(stagingRepository, deploymentRepository, version);
}
private void deployLocal(ReleaseDescriptor releaseDescriptor)
throws MalformedURLException, ArtifactDeploymentException,
ReleaseExecutionException, MojoFailureException {
deploymentRepository = RepositoryUtil
.createRepository(releaseDescriptor.getDeploymentRepository());
stagingRepository = RepositoryUtil.createRepository(releaseDescriptor
.getTempDeploymentRepository());
localRepository = new DefaultArtifactRepository("local", new File(
releaseDescriptor.getLocalRepository()).toURL().toString(),
new DefaultRepositoryLayout());
for (Artifact a : getArtifacts(stagingRepository.getBasedir()))
deployArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
}
private List<Artifact> getArtifacts(String basedir) {
DirectoryScanner ds = new DirectoryScanner();
ds.setIncludes(new String[] { "**/*.pom" });
ds.setBasedir(basedir);
ds.scan();
String[] includedFiles = ds.getIncludedFiles();
List<Artifact> result = new ArrayList<Artifact>();
for (String s : includedFiles) {
s = s.substring(0, s.lastIndexOf(File.separatorChar));
int i = s.lastIndexOf(File.separatorChar);
String version = s.substring(i + 1);
s = s.substring(0, i);
i = s.lastIndexOf(File.separatorChar);
String artifactId = s.substring(i + 1);
String groupId = s.substring(0, i).replace(File.separatorChar, '.');
Artifact artifact = artifactFactory.createArtifactWithClassifier(
groupId, artifactId, version, "pom", null);
result.add(artifact);
System.out.printf("%s %s %s\n", groupId, artifactId, version);
}
return result;
}
public ReleaseResult simulate(ReleaseDescriptor releaseDescriptor,
Settings settings, List reactorProjects)
throws ReleaseExecutionException, ReleaseFailureException {
ReleaseResult result = new ReleaseResult();
result.setResultCode(ReleaseResult.ERROR);
return result;
}
/**
* @plexus.requirement
*/
private ArtifactFactory artifactFactory;
/**
* @plexus.requirement
*/
private ArtifactDeployer artifactDeployer;
public void deployArtifact(String groupId, String artifactId, String version)
throws ArtifactDeploymentException, ReleaseExecutionException {
Artifact pomArtifact = artifactFactory.createArtifactWithClassifier(
groupId, artifactId, version, "pom", null);
String basedir = ((Repository) stagingRepository).getBasedir();
File pomFile = new File(basedir, stagingRepository.pathOf(pomArtifact));
Model model = readModel(pomFile);
Artifact artifact = artifactFactory.createArtifactWithClassifier(
groupId, artifactId, version, model.getPackaging(), null);
File file = new File(basedir, stagingRepository.pathOf(artifact));
ArtifactMetadata metadata = new ProjectArtifactMetadata(artifact,
pomFile);
artifact.addMetadata(metadata);
artifact.setRelease(true);
artifactDeployer.deploy(file, artifact, deploymentRepository,
localRepository);
DirectoryScanner ds = new DirectoryScanner();
ds.setBasedir(file.getParent());
ds.setExcludes(new String[] { "*.md5", "*.sha1", pomFile.getName(),
file.getName() });
ds.scan();
Pattern pattern = Pattern.compile(artifactId + "-" + version
+ "-(.*)\\.(.*)");
for (String s : ds.getIncludedFiles()) {
Matcher m = pattern.matcher(s);
if (!m.matches()) {
throw new IllegalArgumentException("File does not match!");
}
String classifier = m.group(1);
String type = m.group(2);
Artifact attached = artifactFactory.createArtifactWithClassifier(
groupId, artifactId, version, type, classifier);
artifactDeployer.deploy(new File(file.getParent(), s), attached,
deploymentRepository, localRepository);
}
}
/**
* Extract the Model from the specified file.
*
* @param pomFile
* @return
* @throws MojoExecutionException
* if the file doesn't exist of cannot be read.
*/
protected Model readModel(File pomFile) throws ReleaseExecutionException {
if (!pomFile.exists()) {
throw new ReleaseExecutionException(
"Specified pomFile does not exist");
}
Reader reader = null;
try {
reader = new FileReader(pomFile);
MavenXpp3Reader modelReader = new MavenXpp3Reader();
return modelReader.read(reader);
} catch (FileNotFoundException e) {
throw new ReleaseExecutionException(
"Error reading specified POM file: " + e.getMessage(), e);
} catch (IOException e) {
throw new ReleaseExecutionException(
"Error reading specified POM file: " + e.getMessage(), e);
} catch (XmlPullParserException e) {
throw new ReleaseExecutionException(
"Error reading specified POM file: " + e.getMessage(), e);
} finally {
IOUtil.close(reader);
}
}
}