![JAR search and dependency download from the Maven repository](/logo.png)
protoj.lang.PublishFeature Maven / Gradle / Ivy
Show all versions of protoj-jdk6 Show documentation
/**
* 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;
}
}