package org.codehaus.mojo.repositorytools.components; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.maven.archiva.discoverer.ArtifactDiscoverer; import org.apache.maven.archiva.discoverer.DiscovererException; 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.manager.WagonManager; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata; import org.apache.maven.artifact.repository.metadata.GroupRepositoryMetadata; import org.apache.maven.artifact.repository.metadata.Metadata; import org.apache.maven.artifact.repository.metadata.Plugin; import org.apache.maven.artifact.repository.metadata.RepositoryMetadata; import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager; import org.apache.maven.artifact.repository.metadata.RepositoryMetadataResolutionException; import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader; import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.project.artifact.ProjectArtifactMetadata; import org.apache.maven.wagon.ConnectionException; import org.apache.maven.wagon.ResourceDoesNotExistException; import org.apache.maven.wagon.TransferFailedException; import org.apache.maven.wagon.UnsupportedProtocolException; import org.apache.maven.wagon.Wagon; import org.apache.maven.wagon.authentication.AuthenticationException; import org.apache.maven.wagon.authorization.AuthorizationException; import org.apache.maven.wagon.repository.Repository; import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; /** * @plexus.component role="org.codehaus.mojo.repositorytools.components.RepositoryDeployer" * role-hint="default" * @author tom * */ public class DefaultRepositoryDeployer extends AbstractLogEnabled implements RepositoryDeployer { /** * @plexus.requirement */ private ArtifactFactory artifactFactory; /** * @plexus.requirement */ private WagonManager wagonManager; /** * @plexus.requirement */ private ArtifactDeployer deployer; /** * @plexus.requirement role="org.apache.maven.archiva.discoverer.ArtifactDiscoverer" role-hint="wagon" */ private ArtifactDiscoverer discoverer; /** * @plexus.requirement */ private RepositoryMetadataManager repositoryMetadataManager; private File[] findMetadataFiles(String path, ArtifactRepository local) { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(local.getBasedir()); scanner.setIncludes(new String[] { path + "maven-metadata-*.xml", path + "maven-metadata.xml" }); scanner.setExcludes(new String[] { path + "maven-metadata-remote.xml" }); scanner.scan(); String[] paths = scanner.getIncludedFiles(); File[] result = new File[paths.length]; for (int i = 0; i < paths.length; i++) { result[i] = new File(local.getBasedir(), paths[i]); } return result; } public Set deployArtifacts(Set artifacts, ArtifactRepository local, ArtifactRepository remote) throws RepositoryToolsException { List failed = new ArrayList(); // <Artifact> Set success = new HashSet(); // <Artifact> for (Iterator iterator = artifacts.iterator(); iterator.hasNext();) { Artifact artifact = (Artifact) iterator.next(); try { if (artifact.getType().equals("pom")) { loadMetadata(artifact, local, remote); } deployer.deploy(artifact.getFile(), artifact, remote, local); Artifact signature = createSignatureArtifact(artifact); File signatureFile = new File(local.getBasedir(), local .pathOf(signature)); if (signatureFile.exists()) { deployer.deploy(signatureFile, signature, remote, local); } success.add(artifact); } catch (ArtifactDeploymentException e) { failed.add(artifact); getLogger().debug("Could not deploy artifact " + artifact, e); } } for (Iterator iterator = success.iterator(); iterator.hasNext();) { Artifact a = (Artifact) iterator.next(); getLogger().info("Artifact " + a + " deployed"); } for (Iterator iterator = failed.iterator(); iterator.hasNext();) { Artifact a = (Artifact) iterator.next(); getLogger().warn("Artifact " + a + " could not be deployed"); } if (!failed.isEmpty()) { throw new RepositoryToolsException( "Some artifacts could not be deployed"); } return success; } private void loadMetadata(Artifact artifact, ArtifactRepository source, ArtifactRepository remote) throws RepositoryToolsException { // artifact.addMetadata(new ProjectArtifactMetadata(artifact, artifact // .getFile())); String path = artifact.getGroupId().replace('.', File.separatorChar) + File.separator + artifact.getArtifactId() + File.separator; ArtifactRepositoryMetadata artifactMetadata = new ArtifactRepositoryMetadata( artifact); loadMetadata(path, artifactMetadata, source, remote); artifact.addMetadata(artifactMetadata); GroupRepositoryMetadata groupMetadata = new GroupRepositoryMetadata( artifact.getGroupId()); path = artifact.getGroupId().replace('.', File.separatorChar) + File.separator; loadMetadata(path, groupMetadata, source, remote); List plugins = groupMetadata.getMetadata().getPlugins(); Iterator it = plugins.iterator(); while (it.hasNext()) { Plugin plugin = (Plugin) it.next(); if (!plugin.getArtifactId().equals(artifact.getArtifactId())) { it.remove(); } } artifact.addMetadata(groupMetadata); } private Artifact createSignatureArtifact(Artifact artifact) { Artifact signature; if (artifact.getClassifier() != null) { signature = artifactFactory.createArtifactWithClassifier(artifact .getGroupId(), artifact.getArtifactId(), artifact .getVersion(), "asc", artifact.getClassifier() + "." + artifact.getArtifactHandler().getExtension()); } else { signature = artifactFactory.createArtifactWithClassifier(artifact .getGroupId(), artifact.getArtifactId(), artifact .getVersion(), artifact.getArtifactHandler().getExtension() + ".asc", null); } return signature; } private void removeExistingArtifacts(List artifacts, ArtifactRepository remote, Wagon wagon) throws RepositoryToolsException { for (Iterator iterator = artifacts.iterator(); iterator.hasNext();) { Artifact artifact = (Artifact) iterator.next(); try { File temp = File.createTempFile("DeployMojo-", ".tmp"); temp.deleteOnExit(); String remotePath = remote.pathOf(artifact); wagon.get(remotePath, temp); if (!FileUtils.contentEquals(artifact.getFile(), temp)) { throw new TransferFailedException("Remote file found for " + artifact + ", but it is different from the local file!"); } // if we get to here, we could retrieve an existing file, // and it it the same as the current file // -> we won't deploy iterator.remove(); } catch (TransferFailedException e) { throw new RepositoryToolsException( "Could not authenticate to target repository", e); } catch (ResourceDoesNotExistException e) { // expected exception // the resource doesn't exist, so we can deploy } catch (AuthorizationException e) { throw new RepositoryToolsException( "Could not authenticate to target repository", e); } catch (IOException e) { throw new RepositoryToolsException(e); } } } private void loadMetadata(String path, RepositoryMetadata repoMetadata, ArtifactRepository source, ArtifactRepository remote) throws RepositoryToolsException { if (!remote.getProtocol().equals("file")) { try { repositoryMetadataManager.resolveAlways(repoMetadata, source, remote); } catch (RepositoryMetadataResolutionException e) { throw new RepositoryToolsException( "Could not get remote metadata"); } } else { String targetMetadata = "maven-metadata-" + remote.getId() + ".xml"; File[] metadataFiles = findMetadataFiles(path, source); try { for (int i = 0; i < metadataFiles.length; i++) { File metadataFile = metadataFiles[i]; if (!metadataFile.getName().equals(targetMetadata)) { Reader fileReader = new FileReader(metadataFile); MetadataXpp3Reader mappingReader = new MetadataXpp3Reader(); Metadata metadata = mappingReader.read(fileReader); if (repoMetadata.getMetadata() != null) { repoMetadata.getMetadata().merge(metadata); } else { repoMetadata.setMetadata(metadata); } } else { // ignore metadata for the target repository // this will be merged on deployment } } } catch (IOException e) { throw new RepositoryToolsException("Could not load metadata", e); } catch (XmlPullParserException e) { throw new RepositoryToolsException("Could not load metadata", e); } } } public Set getDeployableArtifacts(ArtifactRepository local, ArtifactRepository target, boolean checkExisting) throws RepositoryToolsException { try { List artifacts = discoverer.discoverArtifacts(local, new ArrayList(), new ArtifactFilter() { public boolean include(Artifact artifact) { if (artifact.getFile().getName().endsWith(".tmp")) { return false; } return true; } }); String protocol = target.getProtocol(); Wagon wagon = wagonManager.getWagon(protocol); wagon.connect(new Repository(target.getId(), target.getUrl()), wagonManager.getAuthenticationInfo(target.getId()), wagonManager.getProxy(protocol)); if (checkExisting) { removeExistingArtifacts(artifacts, target, wagon); } wagon.disconnect(); return new HashSet(artifacts); } catch (UnsupportedProtocolException e) { throw new RepositoryToolsException("Protocol not supported: " + target.getProtocol()); } catch (ConnectionException e) { throw new RepositoryToolsException("Could not connect to remote: " + target.getUrl()); } catch (AuthenticationException e) { throw new RepositoryToolsException( "Could not authenticate to remote repository"); } catch (DiscovererException e) { throw new RepositoryToolsException( "Could not discover artifacts in local repository"); } } }