/** * Copyright © 2006-2016 Web Cohesion (info@webcohesion.com) * * Licensed 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. */ package com.webcohesion.enunciate.mojo; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.webcohesion.enunciate.Enunciate; import com.webcohesion.enunciate.artifacts.ArtifactType; import com.webcohesion.enunciate.artifacts.ClientLibraryArtifact; import com.webcohesion.enunciate.artifacts.FileArtifact; 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.ArtifactRepositoryLayout; import org.apache.maven.model.Model; import org.apache.maven.model.Parent; 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.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.*; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectHelper; import org.apache.maven.project.artifact.ProjectArtifactMetadata; import org.codehaus.plexus.PlexusConstants; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.context.Context; import org.codehaus.plexus.context.ContextException; import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; /** * Deploy an Enunciate-generated artifact as if it were in its own project. * * @author Ryan Heaton */ @Mojo ( name = "deploy-artifact", defaultPhase = LifecyclePhase.DEPLOY, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME ) public class DeployArtifactBaseMojo extends AbstractMojo implements Contextualizable { private static final Pattern ALT_REPO_SYNTAX_PATTERN = Pattern.compile("(.+)::(.+)::(.+)"); @Component protected ArtifactDeployer deployer; @Parameter( defaultValue = "${localRepository}", readonly = true, required = true) protected ArtifactRepository localRepository; @Component protected MavenProjectHelper projectHelper; @Parameter( required = true ) protected String enunciateArtifactId; @Parameter( defaultValue = "${project.distributionManagementArtifactRepository}", readonly = true ) protected ArtifactRepository deploymentRepository; /** * Specifies an alternative repository to which the project artifacts should be deployed ( other * than those specified in <distributionManagement> ). * <br/> * Format: id::layout::url */ @Parameter( defaultValue = "${altDeploymentRepository}" ) protected String altDeploymentRepository; /** * Contextualized. */ protected PlexusContainer container; /** * Group id of the artifact to be deployed. Retrieved from POM file if specified. */ @Parameter( defaultValue = "${project.groupId}") protected String groupId; /** * ArtifactId of the artifact to be deployed. Retrieved from POM file if specified. */ @Parameter( defaultValue = "${project.artifactId}-client") protected String artifactId; /** * Version of the artifact to be deployed. Retrieved from POM file if specified. */ @Parameter( defaultValue = "${project.version}") protected String version; /** * Type of the artifact to be deployed. Retrieved from POM file if specified. */ @Parameter protected String packaging; /** * Description passed to a generated POM file (in case of generatePom=true) */ @Parameter protected String description; /** * Component used to create an artifact */ @Component protected ArtifactFactory artifactFactory; /** * Location of an existing POM file to be deployed alongside the artifact(s). */ @Parameter protected File pomFile; /** * Upload a POM for the artifact(s) to be deployed. Will generate a default POM if none is supplied with the pomFile argument. */ @Parameter( defaultValue = "true") protected boolean generatePom; /** * Add classifier to the artifact */ @Parameter protected String classifier; public void execute() throws MojoExecutionException, MojoFailureException { if (this.enunciateArtifactId == null) { throw new MojoExecutionException("An enunciate artifact id must be supplied."); } Enunciate enunciate = (Enunciate) getPluginContext().get(ConfigMojo.ENUNCIATE_PROPERTY); if (enunciate == null) { throw new MojoExecutionException("No enunciate mechanism found in the project!"); } com.webcohesion.enunciate.artifacts.Artifact enunciateArtifact = enunciate.findArtifact(this.enunciateArtifactId); if (enunciateArtifact == null) { throw new MojoExecutionException("Unknown Enunciate artifact: " + this.enunciateArtifactId + "."); } File mainArtifact = null; File sources = null; File javadocs = null; if (enunciateArtifact instanceof ClientLibraryArtifact) { for (com.webcohesion.enunciate.artifacts.Artifact childArtifact : ((ClientLibraryArtifact) enunciateArtifact).getArtifacts()) { if (childArtifact instanceof FileArtifact) { ArtifactType artifactType = ((FileArtifact) childArtifact).getArtifactType(); if (artifactType != null) { switch (artifactType) { case binaries: mainArtifact = ((FileArtifact) childArtifact).getFile(); break; case sources: sources = ((FileArtifact) childArtifact).getFile(); break; case javadocs: javadocs = ((FileArtifact) childArtifact).getFile(); break; } } } } } else if (enunciateArtifact instanceof FileArtifact) { mainArtifact = ((FileArtifact) enunciateArtifact).getFile(); } else { try { mainArtifact = enunciate.createTempFile(this.enunciateArtifactId, "artifact"); enunciateArtifact.exportTo(mainArtifact, enunciate); } catch (IOException e) { throw new MojoExecutionException("Unable to create a temp file.", e); } } if (mainArtifact == null) { if (sources != null) { mainArtifact = sources; sources = null; } } if (mainArtifact == null) { throw new MojoExecutionException("Unable to determine the file to deploy from enunciate artifact " + enunciateArtifactId + "."); } // Process the supplied POM (if there is one) Model model = null; if (pomFile != null) { generatePom = false; model = readModel(pomFile); processModel(model); } if (this.packaging == null) { String artifactName = mainArtifact.getName(); int dotIndex = artifactName.indexOf('.'); if (dotIndex > 0 && (dotIndex + 1 < artifactName.length())) { this.packaging = artifactName.substring(dotIndex + 1); } } if (this.packaging == null) { throw new MojoExecutionException("Unable to determine the packaging of enunciate artifact " + enunciateArtifactId + ". Please specify it in the configuration."); } if (this.version == null) { throw new MojoExecutionException("Null version."); } if (model == null) { model = new Model(); model.setModelVersion("4.0.0"); model.setGroupId(this.groupId); model.setArtifactId(this.artifactId); model.setVersion(this.version); model.setPackaging(this.packaging); model.setDescription(this.description); } ArtifactRepository repo = getDeploymentRepository(); String protocol = repo.getProtocol(); if (protocol.equals("scp")) { File sshFile = new File(System.getProperty("user.home"), ".ssh"); if (!sshFile.exists()) { sshFile.mkdirs(); } } Artifact artifact = this.artifactFactory.createArtifactWithClassifier(groupId, artifactId, version, packaging, classifier); // Upload the POM if requested, generating one if need be if (generatePom) { ArtifactMetadata metadata = new ProjectArtifactMetadata(artifact, generatePomFile(model)); artifact.addMetadata(metadata); } else { ArtifactMetadata metadata = new ProjectArtifactMetadata(artifact, pomFile); artifact.addMetadata(metadata); } try { getDeployer().deploy(mainArtifact, artifact, repo, this.localRepository); if (sources != null || javadocs != null) { MavenProject project = new MavenProject(model); project.setArtifact(artifact); if (sources != null) { //we have to do it this way because of classloading issues. this.projectHelper.attachArtifact(project, artifact.getType(), "sources", sources); getDeployer().deploy(sources, (Artifact) project.getAttachedArtifacts().get(0), repo, this.localRepository); } if (javadocs != null) { //we have to do it this way because of classloading issues. this.projectHelper.attachArtifact(project, artifact.getType(), "javadoc", javadocs); getDeployer().deploy(javadocs, (Artifact) project.getAttachedArtifacts().get(0), repo, this.localRepository); } } } catch (ArtifactDeploymentException e) { throw new MojoExecutionException(e.getMessage(), e); } } public ArtifactDeployer getDeployer() { return deployer; } // private ArtifactRepository getDeploymentRepository() throws MojoExecutionException, MojoFailureException { if (deploymentRepository == null && altDeploymentRepository == null) { String msg = "Deployment failed: repository element was not specified in the pom inside" + " distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter"; throw new MojoExecutionException(msg); } ArtifactRepository repo = null; if (altDeploymentRepository != null) { getLog().info("Using alternate deployment repository " + altDeploymentRepository); Matcher matcher = ALT_REPO_SYNTAX_PATTERN.matcher(altDeploymentRepository); if (!matcher.matches()) { throw new MojoFailureException(altDeploymentRepository, "Invalid syntax for repository.", "Invalid syntax for alternative repository. Use \"id::layout::url\"."); } else { String id = matcher.group(1).trim(); String layout = matcher.group(2).trim(); String url = matcher.group(3).trim(); ArtifactRepositoryLayout repoLayout; try { repoLayout = (ArtifactRepositoryLayout) container.lookup(ArtifactRepositoryLayout.ROLE, layout); } catch (ComponentLookupException e) { throw new MojoExecutionException("Cannot find repository layout: " + layout, e); } repo = new DefaultArtifactRepository(id, url, repoLayout); } } if (repo == null) { repo = deploymentRepository; } return repo; } public void contextualize(Context context) throws ContextException { this.container = (PlexusContainer) context.get(PlexusConstants.PLEXUS_KEY); } /** * Process the supplied pomFile to get groupId, artifactId, version, and packaging * * @throws NullPointerException if model is <code>null</code> */ private void processModel(Model model) { Parent parent = model.getParent(); if (this.groupId == null) { if (parent != null && parent.getGroupId() != null) { this.groupId = parent.getGroupId(); } if (model.getGroupId() != null) { this.groupId = model.getGroupId(); } } if (this.artifactId == null && model.getArtifactId() != null) { this.artifactId = model.getArtifactId(); } if (this.version == null && model.getVersion() != null) { this.version = model.getVersion(); } if (this.packaging == null && model.getPackaging() != null) { this.packaging = model.getPackaging(); } } protected Model readModel(File pomFile) throws MojoExecutionException { if (!pomFile.exists()) { throw new MojoExecutionException("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 MojoExecutionException("Error reading specified POM file: " + e.getMessage(), e); } catch (IOException e) { throw new MojoExecutionException("Error reading specified POM file: " + e.getMessage(), e); } catch (XmlPullParserException e) { throw new MojoExecutionException("Error reading specified POM file: " + e.getMessage(), e); } finally { IOUtil.close(reader); } } private File generatePomFile(Model model) throws MojoExecutionException { FileWriter fw = null; try { File tempFile = File.createTempFile("mvninstall", ".pom"); tempFile.deleteOnExit(); fw = new FileWriter(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); } } }