org.nuiton.jredmine.plugin.announcement.AbstractAnnouncementMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jredmine-maven-plugin Show documentation
Show all versions of jredmine-maven-plugin Show documentation
JRedmine maven plugin to interacts with Redmine's server
/*
* #%L
* JRedmine :: Maven plugin
*
* $Id$
* $HeadURL$
* %%
* Copyright (C) 2009 - 2012 Tony Chemit, CodeLutin
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.jredmine.plugin.announcement;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.changes.ChangesXML;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.velocity.VelocityComponent;
import org.nuiton.jredmine.model.Attachment;
import org.nuiton.jredmine.plugin.AbstractRedmineMojoWithProjectAndVersion;
import org.nuiton.jredmine.plugin.SkipOrRunOnlyOnceAware;
import org.nuiton.plugin.PluginHelper;
import java.io.File;
import java.util.List;
import java.util.Map;
/**
* @author tchemit
*/
public abstract class AbstractAnnouncementMojo extends AbstractRedmineMojoWithProjectAndVersion implements AnnouncementGeneratorConfiguration, SkipOrRunOnlyOnceAware {
///////////////////////////////////////////////////////////////////////////
/// Mojo parameters
///////////////////////////////////////////////////////////////////////////
/**
* Directory where the template file will be generated.
*
* @since 1.0.0
*/
@Parameter(property = "redmine.templateOutputDirectory", defaultValue = "${project.build.directory}/generated-sources/announcement", required = true)
protected File templateOutputDirectory;
/**
* The path of the changes.xml file.
*
* @since 1.0.0
*/
@Parameter(property = "redmine.xmlPath", defaultValue = "${basedir}/src/changes/changes.xml", required = true)
protected File xmlPath;
/**
* Directory that contains the template.
*
* Note: This directory must be a subdirectory of
* /src/main/resources/ or current project base directory
.
*
*
* @since 1.0.0
*/
@Parameter(property = "redmine.templateDirectory", defaultValue = "org/nuiton/jredmine/plugin/announcement", required = true)
protected String templateDirectory = "org/nuiton/jredmine/plugin/announcement";
/**
* The template encoding.
*
* @since 1.0.0
*/
@Parameter(property = "redmine.templateEncoding", defaultValue = "${project.build.sourceEncoding}")
protected String templateEncoding;
/**
* Map which will be pass to the velocity context
*
* @since 1.0.0
*/
@Parameter
protected Map announceParameters;
/**
* Template strings per system that is used to discover the URL to use to display an attchment. Each key in this
* map denotes the (case-sensitive) identifier of the issue tracking system and its value gives the URL template.
*
* There are 2 template tokens you can use. %URL%
: this is computed by getting the
* <issueManagement>/<url>
value from the POM, and removing the last '/'
* and everything that comes after it. %FILE%
: this is the issue number.
*
*
* @since 1.0.0
*/
@Parameter(property = "redmine.attachmentLinkTemplate", defaultValue = "%URL%/attachments/download/%FILE%")
protected String attachmentLinkTemplate = "%URL%/attachments/download/%FILE%";
/**
* Current maven project groupId.
*
* @since 1.0.0
*/
@Parameter(property = "session.topLevelProject.groupId", readonly = true)
protected String groupId;
/**
* current project artifactId.
*
* @since 1.0.0
*/
@Parameter(property = "session.topLevelProject.artifactId", readonly = true)
protected String artifactId;
/**
* Distribution url of the artifact.
*
* @since 1.0.0
*/
@Parameter(property = "redmine.projectUrl", defaultValue = "${session.topLevelProject.url}", required = true)
protected String projectUrl;
/**
* Packaging structure for the artifact.
*
* @since 1.0.0
*/
@Parameter(property = "project.packaging", readonly = true)
protected String packaging;
/**
* The name of the artifact to be used in the announcement.
*
* @since 1.0.0
*/
@Parameter(property = "redmine.finalName", defaultValue = "${session.topLevelProject.build.finalName}", required = true)
protected String finalName;
/**
* The current project base directory.
*
* @since 1.0.0
*/
@Parameter(property = "basedir", required = true)
protected String basedir;
/**
* URL where the artifact can be downloaded. If not specified,
* no URL is used.
*
* @parameter
* @since 1.0.0
*/
@Parameter
protected String urlDownload;
/**
* Name of the team that develops the artifact.
*
* @required
* @since 1.0.0
*/
@Parameter(property = "redmine.developmentTeam", defaultValue = "${session.topLevelProject.name} team", required = true)
protected String developmentTeam;
/**
* Short description or introduction of the released artifact.
*
* @since 1.0.0
*/
@Parameter(property = "redmine.introduction", defaultValue = "${session.topLevelProject.description}")
protected String introduction;
/**
* A flag to restrict only one run in a build (for multi-module context).
*
* @since 1.0.0
*/
@Parameter(property = "redmine.runOnce", defaultValue = "true")
protected boolean runOnce;
/**
* A flag to restrict only to run on root module.
*
* @since 1.6
*/
@Parameter(property = "redmine.runOnlyOnRoot", defaultValue = "true")
protected boolean runOnlyOnRoot;
/**
* Files where are stored location of artifacts to deploy by the build.
*
* @since 1.2.1
*/
@Parameter(property = "redmine.artifactsFile")
protected File artifactsFile;
/**
* Deployement url (for artifacts).
*
* @since 1.2.1
*/
@Parameter(property = "redmine.deploymentUrl", readonly = true)
protected String deploymentUrl;
///////////////////////////////////////////////////////////////////////////
/// Mojo components
///////////////////////////////////////////////////////////////////////////
/**
* Velocity Component.
*
* @since 1.0.0
*/
@Component(hint = "jredmine-maven-plugin")
protected VelocityComponent velocity;
///////////////////////////////////////////////////////////////////////////
/// Mojo internal attributes
///////////////////////////////////////////////////////////////////////////
protected Attachment[] attachments;
protected Map artifactUrls;
protected Map attachmentUrls;
protected List> releases;
protected AnnouncementGenerator generator;
/** flag to mark if a runOnce goal was done */
protected boolean runOnceDone;
///////////////////////////////////////////////////////////////////////////
/// AbstractAnnouncementMojo
///////////////////////////////////////////////////////////////////////////
/** @return the name fo the template to use */
protected abstract String getAnnouncementTemplate();
protected AbstractAnnouncementMojo() {
super(true, true);
}
///////////////////////////////////////////////////////////////////////////
/// AnnouncementGeneratorConfiguration
///////////////////////////////////////////////////////////////////////////
@Override
public String getAttachmentLinkTemplate() {
return attachmentLinkTemplate;
}
@Override
public String getArtifactId() {
return artifactId;
}
@Override
public Map getArtifactUrls() {
return artifactUrls;
}
@Override
public Map getAttachmentUrls() {
return attachmentUrls;
}
@Override
public String getBasedir() {
return basedir;
}
@Override
public String getDeploymentUrl() {
return deploymentUrl;
}
@Override
public String getDevelopmentTeam() {
return developmentTeam;
}
@Override
public String getFinalName() {
return finalName;
}
@Override
public String getGroupId() {
return groupId;
}
@Override
public String getIntroduction() {
return introduction;
}
@Override
public String getPackaging() {
return packaging;
}
@Override
public String getProjectUrl() {
return projectUrl;
}
@Override
public String getUrlDownload() {
return urlDownload;
}
@Override
public Map getAnnounceParameters() {
return announceParameters;
}
///////////////////////////////////////////////////////////////////////////
/// SkipOrRunOnlyOnceAware
///////////////////////////////////////////////////////////////////////////
@Override
public boolean isRunOnce() {
return runOnce;
}
@Override
public boolean isRunOnlyOnRoot() {
return runOnlyOnRoot;
}
@Override
public boolean isRunOnceDone() {
return runOnceDone;
}
@Override
public boolean checkRunOnceDone() {
// compute unique key
StringBuilder buffer = new StringBuilder(getClass().getName());
buffer.append("##").append(projectId);
buffer.append("##").append(versionId);
buffer.append("##").append(releaseVersion);
buffer.append("##").append(getAnnouncementTemplate());
String key = buffer.toString();
return !needInvoke(runOnce, runOnlyOnRoot, key);
}
///////////////////////////////////////////////////////////////////////////
/// AbstractPlugin
///////////////////////////////////////////////////////////////////////////
@Override
protected void init() throws Exception {
if (isGoalSkip()) {
return;
}
versionId = PluginHelper.removeSnapshotSuffix(versionId);
if (runOnceDone = isRunOnce() && checkRunOnceDone()) {
return;
}
if (!xmlPath.exists()) {
throw new MojoExecutionException(
"can not find redmine-template at " + xmlPath);
}
if (StringUtils.isEmpty(templateEncoding)) {
templateEncoding = ReaderFactory.FILE_ENCODING;
getLog().warn(
"File encoding has not been set, using platform encoding " +
templateEncoding + ", i.e. build is platform dependent!");
}
// if (StringUtils.isEmpty(introduction)) {
// introduction = project.getUrl();
// }
generator = new AnnouncementGenerator(this);
if (artifactsFile != null) {
if (!artifactsFile.exists()) {
throw new MojoExecutionException("The artifactsFile [" +
artifactsFile + "] does not exists");
}
File[] files = PluginHelper.getLinesAsFiles(artifactsFile);
String url = deploymentUrl.trim();
if (!url.endsWith("/")) {
deploymentUrl = url += "/";
}
if (isVerbose()) {
getLog().info("Deploy url = " + url);
}
artifactUrls = generator.getArtifactsUrls(url, versionId, isVerbose(), files);
}
super.init();
Attachment[] attachments = service.getAttachments(projectId, versionId);
if (attachments.length == 0) {
getLog().info("No attachments files");
} else {
if (isVerbose()) {
getLog().info("attachmentLinkTemplate " +
attachmentLinkTemplate);
getLog().info("server url " + url);
}
attachmentUrls = generator.getAttachmentsUrls(attachments);
}
if (isVerbose() && attachmentUrls != null) {
for (Map.Entry e : attachmentUrls.entrySet()) {
Attachment key = e.getKey();
String value = e.getValue();
getLog().info("attachment file " + key.getFilename() + " --> " + value);
}
}
ChangesXML changesXml = new ChangesXML(xmlPath, getLog());
releases = changesXml.getReleaseList();
}
@Override
protected void doAction() throws Exception {
//TODO-TC-20091209 must obtain back the full name of dev from the project team on each action
String template = getAnnouncementTemplate();
File out = getOutputFile();
getLog().info("Apply template [" + template + "]");
getLog().info(" from : " + xmlPath);
getLog().info(" to : " + out);
VelocityEngine engine = velocity.getEngine();
engine.setApplicationAttribute("baseDirectory", basedir);
Context context = generator.createVelocityContext(releases);
generator.doGenerate(engine,
context,
out,
templateDirectory + "/" + template,
templateEncoding
);
getLog().debug("Created announcement [" + template + "] in " + out);
}
///////////////////////////////////////////////////////////////////////////
/// Others
///////////////////////////////////////////////////////////////////////////
protected File getOutputFile() {
return new File(templateOutputDirectory, getAnnouncementTemplate());
}
}