All Downloads are FREE. Search and download functionalities are using the official Maven repository.

protoj.lang.PublishFeature Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2009 Ashley Williams
 * 
 * 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 protoj.lang;

import java.io.File;

import org.apache.maven.artifact.ant.AttachedArtifact;
import org.apache.maven.artifact.ant.Authentication;
import org.apache.maven.artifact.ant.DeployTask;
import org.apache.maven.artifact.ant.InstallWagonProviderTask;
import org.apache.maven.artifact.ant.Pom;
import org.apache.maven.artifact.ant.RemoteRepository;
import org.apache.tools.ant.Project;

import protoj.lang.ClassesArchive.ClassesEntry;
import protoj.lang.JavadocArchive.JavadocEntry;
import protoj.lang.internal.InformationException;
import protoj.util.AntTarget;
import protoj.util.ArgRunnable;
import protoj.util.CommandTask;

/**
 * Publishes project artifacts to a maven repository by performing a maven
 * deploy. The details of the repository must be configured through the API
 * 
 * 
 * @author Ashley Williams
 * 
 */
public final class PublishFeature {
	/**
	 * See {@link #getParent()}.
	 */
	private final StandardProject parent;

	/**
	 * The instance used for additional feature configuration.
	 */
	private ArgRunnable config;

	/**
	 * See {@link #getCurrentDeployTask()}.
	 */
	private DeployTask currentDeployTask;

	/**
	 * See {@link #getCurrentPom()}.
	 */
	private Pom currentPom;

	/**
	 * The artifact id for the maven wagon provider.
	 */
	private String providerArtifactId;

	/**
	 * The version for the maven wagon provider.
	 */
	private String providerVersion;

	/**
	 * See {@link #getUrl()}.
	 */
	private String url;

	/**
	 * See {@link #getWorkingDir()}.
	 */
	private File workingDir;

	/**
	 * See {@link #getCurrentClassesEntry()}.
	 */
	private ClassesEntry currentClassesEntry;

	/**
	 * An example of a url is
	 * "scp://shell.sourceforge.net:/home/users/a/ag/agwilliams10000". Since
	 * this example url uses the scp protocol,
	 * {@link #initProvider(String, String)} must be called as follows:
	 * 
	 * 
	 * pub.initProvider("wagon-ssh", "1.0-beta-2");
	 * 
* * See the maven documentation for more information. * * * @param parent * the owner of this feature * @param url * the location that the artifact should be published to */ public PublishFeature(StandardProject parent, String url) { this.parent = parent; this.url = url; } /** * The provided config argument is called back when {@link #deploy} is * invoked so that further configuration of this feature may be applied. * * @param config */ public void initConfig(ArgRunnable config) { this.config = config; } /** * If a url is going to be used that uses a transport protocol, use this * method to ensure the appropriate wagon provider is configured. * * @param artifactId * @param version */ public void initProvider(String artifactId, String version) { this.providerArtifactId = artifactId; this.providerVersion = version; } /** * Deploys all registered classes archives that are configured with maven * pom files to the maven repository. Passes each archive to {@link #deploy} * . * * @param userName * @param key * @param passphrase * @param password */ public void deployAll(final String userName, final String key, final String password, final String passphrase) { ArchiveFeature archive = parent.getArchiveFeature(); ClassesArchive classesArchive = archive.getClassesArchive(); classesArchive.visit(new ArgRunnable() { public void run(ClassesEntry entry) { String pomResource = entry.getPomResource(); if ((pomResource != null)) { deploy(entry.getArchiveEntry().getName(), userName, key, password, passphrase); } } }); } /** * Deploys the archive with the given name to the maven repository. The * authentication credentials are passed straight through to the underlying * maven ant tasks, so consult the maven website for more information. * * @param artifactName * the name of the artifact to publish * @param userName * mandatory where a wagon provider has been provided * @param key * can be null if the default ssh client key location is to be * used or if key based authentication isn't configured * @param password * the password to use, usually not null unless a passphrase is * being specified * @param passphrase * the key based authentication passphrase, can be null if a * password is being used or if there is no passphrase for the * private key * */ public void deploy(String artifactName, String userName, String key, String password, String passphrase) { AntTarget target = new AntTarget("publish"); target.initLogging(Project.MSG_INFO); String pomId = "protoj.project"; maybeAddProvider(target); ClassesArchive archive = parent.getArchiveFeature().getClassesArchive(); currentClassesEntry = archive.getEntry(artifactName); currentDeployTask = new DeployTask(); currentPom = addPomTask(target, pomId); assignClassesArtifact(target, pomId, userName, key); attachJavadocArtifact(artifactName); attachSourcesArtifact(artifactName); maybeAttachSignatureFile(currentPom.getFile(), null, "pom"); if (config != null) { config.run(this); } target.execute(); } /** * Adds a new pom task to the specified target. The pom task points to the * pom file whose resource is set up in the {@link ClassesArchive}. * * @param target * @param pomId * @return */ private Pom addPomTask(AntTarget target, String pomId) { ClassesEntry entry = getCurrentClassesEntry(); String pomResource = entry.getPomResource(); if (pomResource == null) { String name = entry.getArchiveEntry().getName(); throw new InformationException( "no pom specified: please specify a pom resource for the artifact called " + name); } ResourceFeature feature = parent.getResourceFeature(); File confDir = parent.getLayout().getConfDir(); File pomFile = feature.filterResourceToDir(pomResource, confDir); Pom pom = new Pom(); pom.setTaskName("publish-pom"); target.addTask(pom); pom.setId(pomId); pom.setFile(pomFile); return pom; } /** * The artifact specified in the {@link ClassesArchive} with the given * artifactName is set on the current deploy task. If signing has been * requested then a signature file for the artifact is attached for * deployment. * * @param target * @param pomId * @param userName * @param key */ private void assignClassesArtifact(AntTarget target, String pomId, String userName, String key) { File classes = getCurrentClassesEntry().getArchiveEntry().getArtifact(); if (classes == null) { throw new InformationException( "no artifact specified: please specify the name of an artifact to publish"); } if (!classes.exists()) { throw new InformationException( "no artifact found: couldn't find an artifact at " + classes.getAbsolutePath()); } RemoteRepository repo = new RemoteRepository(); repo.setUrl(url); Authentication authentication = new Authentication(); authentication.setUserName(userName); if (key != null) { authentication.setPrivateKey(key); } repo.addAuthentication(authentication); currentDeployTask = new DeployTask(); currentDeployTask.addRemoteRepository(repo); currentDeployTask.setTaskName("publish-deploy"); target.addTask(currentDeployTask); currentDeployTask.setFile(classes); currentDeployTask.setPomRefId(pomId); maybeAttachSignatureFile(classes, null, "jar"); } /** * Creates a signature file for the given artifact and attaches it ready for * deployment, but only if signed artifacts has been configured. The * classifier is the bit after the version number in an artifact name eg for * foo-1.1-dev.jar the classifier is "dev". *

* Note that when deploying the name of the source artifact is irrelevant to * maven since it will always use the project artifact id, version, * classifier and extension when forming the final name to go in the * repository. * * @param artifact * the artifact to sign * @param classifier * the classifier of the artifact eg "javadoc" or null if none is * required * @param extension * for example ".pom" or ".jar" */ private void maybeAttachSignatureFile(File artifact, String classifier, String extension) { String gpgOptions = getCurrentClassesEntry().getGpgOptions(); if (gpgOptions != null) { AttachedArtifact attach = currentDeployTask.createAttach(); File artifactSig = createSig(gpgOptions, artifact); attach.setFile(artifactSig); if (classifier != null) { // maven ant task idea of classifier seems different // than maven website as it requires the extension here attach.setClassifier(classifier + "." + extension); attach.setType("asc"); } else { attach.setClassifier(null); attach.setType(extension + ".asc"); } } } /** * Creates a signature file in the working directory for the specified * artifact. The gpgOptions command line call to gpg is used to carry out * the work. * * @param gpgOptions * @param artifact * * @return */ private File createSig(String gpgOptions, File artifact) { String artifactSigName = artifact.getName() + ".asc"; File workingDir = getWorkingDir(); File artifactSig = new File(workingDir, artifactSigName); String line = String.format(gpgOptions, artifact.getAbsolutePath(), artifactSig.getAbsolutePath()); return executeGpgCommand(line, artifact, artifactSig); } /** * This method must not be inlined into {@link #createSig(String, File)} * since it is replaced with an alternative implementation during testing * with an aspect. The reason for this is that setting up keys on each test * machine is too complex. * * @param options * the options to pass to gpg * @param artifact * the file used in the applied advice * @param artifactSig * the file used in the applied advice * @return */ private File executeGpgCommand(String options, File artifact, File artifactSig) { CommandTask task = new CommandTask(getWorkingDir(), "gpg", options, null); task.initSpawn(false); task.execute(); return artifactSig; } /** * If a provider configuration has been specified then a new provider will * be added, otherwise this method does nothing. * * @param target */ private void maybeAddProvider(AntTarget target) { if (isUsingProvider()) { InstallWagonProviderTask provider = new InstallWagonProviderTask(); provider.setTaskName("publish-wagon"); target.addTask(provider); provider.setArtifactId(providerArtifactId); provider.setVersion(providerVersion); } } /** * Attaches the sources artifact associated with the given artifactName to * the deploy task, if any. * * @param artifactName */ private void attachSourcesArtifact(String artifactName) { ArchiveFeature feature = parent.getArchiveFeature(); SourceArchive archive = feature.getSourceArchive(); ArchiveEntry entry = archive.getEntry(artifactName); if (entry != null) { File artifact = entry.getArtifact(); AttachedArtifact attach = currentDeployTask.createAttach(); attach.setFile(artifact); attach.setClassifier("sources"); maybeAttachSignatureFile(artifact, "sources", "jar"); } } /** * Attaches the javadoc artifact associated with the given artifactName to * the deploy task, if any. * * @param artifactName */ private void attachJavadocArtifact(String artifactName) { ArchiveFeature feature = parent.getArchiveFeature(); JavadocArchive archive = feature.getJavadocArchive(); JavadocEntry entry = archive.getEntry(artifactName); if (entry != null) { File artifact = entry.getArchiveEntry().getArtifact(); AttachedArtifact attach = currentDeployTask.createAttach(); attach.setFile(artifact); attach.setClassifier("javadoc"); maybeAttachSignatureFile(artifact, "javadoc", "jar"); } } /** * The parent of this feature. * * @return */ public StandardProject getParent() { return parent; } /** * The task being processed by {@link #deploy}, responsible for copying the * artifacts to the repository. * * @return */ public DeployTask getCurrentDeployTask() { return currentDeployTask; } /** * Represents the artifact that contains the project class files that is * currently being deployed. * * @return */ public ClassesEntry getCurrentClassesEntry() { return currentClassesEntry; } /** * The task being processed by {@link #deploy}, responsible for loading in * the pom file. * * @return */ public Pom getCurrentPom() { return currentPom; } /** * The url where artifacts are published to. * * @return */ public String getUrl() { return url; } /** * Whether or not a maven wagon provider has been configured. * * @return */ public boolean isUsingProvider() { return providerArtifactId != null; } /** * The directory where the ivy and maven files are extracted to. * * @return */ public File getWorkingDir() { if (workingDir == null) { workingDir = new File(parent.getLayout().getTargetDir(), "publish"); workingDir.mkdirs(); } return workingDir; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy