Skip to content

Commit

Permalink
Fix JENKINS-18567, JENKINS-25926 and JENKINS-25719
Browse files Browse the repository at this point in the history
Added ability for users to watch a job.
Fixup the html content coming from CssInliner
Remove adminAddress field for global config
  • Loading branch information
Alex Earl committed Dec 5, 2014
1 parent 6acb6e2 commit bb0053d
Show file tree
Hide file tree
Showing 31 changed files with 839 additions and 303 deletions.
12 changes: 11 additions & 1 deletion pom.xml
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.554.1</version>
<version>1.580.1</version>
</parent>

<licenses>
Expand Down Expand Up @@ -134,6 +134,16 @@
<artifactId>groovy-all</artifactId>
<version>1.8.5</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>junit</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>matrix-project</artifactId>
<version>1.4</version>
</dependency>
</dependencies>

<scm>
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/hudson/plugins/emailext/AttachmentUtils.java
Expand Up @@ -53,7 +53,13 @@ public FilePathDataSource(FilePath file) {
}

public InputStream getInputStream() throws IOException {
return file.read();
InputStream stream = null;
try {
stream = file.read();
} catch(InterruptedException e) {
stream = null;
}
return stream;
}

public OutputStream getOutputStream() throws IOException {
Expand Down
Expand Up @@ -5,8 +5,6 @@
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.Hudson;
import hudson.model.TaskListener;
import hudson.plugins.emailext.plugins.content.JellyScriptContent;
import hudson.plugins.emailext.plugins.content.ScriptContent;
import hudson.util.FormValidation;
Expand Down
77 changes: 52 additions & 25 deletions src/main/java/hudson/plugins/emailext/ExtendedEmailPublisher.java
Expand Up @@ -13,15 +13,14 @@
import hudson.matrix.MatrixAggregator;
import hudson.matrix.MatrixBuild;
import hudson.matrix.MatrixRun;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.model.*;
import hudson.plugins.emailext.plugins.ContentBuilder;
import hudson.plugins.emailext.plugins.CssInliner;
import hudson.plugins.emailext.plugins.EmailTrigger;
import hudson.plugins.emailext.plugins.RecipientProvider;
import hudson.plugins.emailext.plugins.content.TriggerNameContent;
import hudson.plugins.emailext.watching.EmailExtWatchAction;
import hudson.plugins.emailext.watching.EmailExtWatchJobProperty;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.MailMessageIdAction;
import hudson.tasks.Mailer;
Expand All @@ -33,15 +32,7 @@
import java.io.StringWriter;
import java.net.ConnectException;
import java.net.SocketException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.CheckForNull;
Expand Down Expand Up @@ -163,18 +154,10 @@ public ExtendedEmailPublisher(String project_recipient_list, String project_cont
String project_default_content, String project_attachments, String project_presend_script,
int project_attach_buildlog, String project_replyto, boolean project_save_output,
List<EmailTrigger> project_triggers, MatrixTriggerMode matrixTriggerMode) {
this.recipientList = project_recipient_list;
this.contentType = project_content_type;
this.defaultSubject = project_default_subject;
this.defaultContent = project_default_content;
this.attachmentsPattern = project_attachments;
this.presendScript = project_presend_script;
this.attachBuildLog = project_attach_buildlog > 0;
this.compressBuildLog = project_attach_buildlog > 1;
this.replyTo = project_replyto;
this.saveOutput = project_save_output;
this.configuredTriggers = project_triggers;
this.matrixTriggerMode = matrixTriggerMode;

this(project_recipient_list, project_content_type, project_default_subject, project_default_content,
project_attachments, project_presend_script, project_attach_buildlog, project_replyto,
project_save_output, project_triggers, matrixTriggerMode, false, Collections.EMPTY_LIST);
}

@DataBoundConstructor
Expand Down Expand Up @@ -222,6 +205,11 @@ public void setMatrixTriggerMode(MatrixTriggerMode matrixTriggerMode) {
this.matrixTriggerMode = matrixTriggerMode;
}

@Override
public Collection<? extends Action> getProjectActions(AbstractProject<?,?> project) {
return Collections.singletonList(new EmailExtWatchAction(project));
}

public void debug(PrintStream p, String format, Object... args) {
getDescriptor().debug(p, format, args);
}
Expand Down Expand Up @@ -280,6 +268,45 @@ private boolean _perform(AbstractBuild<?, ?> build, Launcher launcher, BuildList
listener.getLogger().println("Trigger " + triggerName + " was overridden by another trigger and will not send an email.");
}

EmailExtWatchJobProperty jprop = build.getParent().getProperty(EmailExtWatchJobProperty.class);

if(jprop != null) {
for(String u : jprop.getWatchers()) {
User user = User.get(u);
if(user != null) {
EmailExtWatchAction.UserProperty prop = user.getProperty(EmailExtWatchAction.UserProperty.class);
if (prop != null) {
final Multimap<String, EmailTrigger> watcherTriggered = ArrayListMultimap.create();
for (EmailTrigger trigger : prop.getTriggers()) {
if (trigger.isPreBuild() == forPreBuild && trigger.trigger(build, listener)) {
String tName = trigger.getDescriptor().getDisplayName();
watcherTriggered.put(tName, trigger);
listener.getLogger().println("Email was triggered for watcher '" + user.getDisplayName() + "' for: " + tName);
emailTriggered = true;
}
}

//Go through and remove triggers that are replaced by others
replacedTriggers = new ArrayList<String>();

for (Object tName : triggered.keySet()) {
String triggerName = (String) tName;
for (EmailTrigger trigger : (Collection<EmailTrigger>) triggered.get(triggerName)) {
replacedTriggers.addAll(trigger.getDescriptor().getTriggerReplaceList());
}
}

for (String triggerName : replacedTriggers) {
watcherTriggered.removeAll(triggerName);
listener.getLogger().println("Trigger " + triggerName + " was overridden by another trigger and will not send an email.");
}

triggered.putAll(watcherTriggered);
}
}
}
}

if (emailTriggered && triggered.isEmpty()) {
listener.getLogger().println("There is a circular trigger replacement with the email triggers. No email is sent.");
return false;
Expand Down
Expand Up @@ -391,6 +391,8 @@ public boolean configure(StaplerRequest req, JSONObject formData)

requireAdminForTemplateTesting = req.hasParameter("ext_mailer_require_admin_for_template_testing");

enableWatching = req.hasParameter("ext_mailer_watching_enabled");

// specify List-ID information
if (req.hasParameter("ext_mailer_use_list_id")) {
listId = nullify(req.getParameter("ext_mailer_list_id"));
Expand Down
44 changes: 30 additions & 14 deletions src/main/java/hudson/plugins/emailext/plugins/CssInliner.java
Expand Up @@ -12,35 +12,41 @@
import java.net.URLConnection;
import java.text.MessageFormat;
import java.util.StringTokenizer;
import org.apache.commons.lang.StringEscapeUtils;

/**
* <p>Inlines CSS to avoid the dreaded GMail Grimace.</p>
* <p>
* Inlines CSS to avoid the dreaded GMail Grimace.</p>
*
* <p>The magic keyword is <code><em>data-inline="true"</em></code>.</p>
* <p>
* The magic keyword is <code><em>data-inline="true"</em></code>.</p>
*
* <ul>
* <li>
* When used in conjunction with the <code>style</code> tag, it inlines the stylesheet defined there into all
* html elements matching the rules.
* When used in conjunction with the <code>style</code> tag, it inlines the
* stylesheet defined there into all html elements matching the rules.
* </li>
* <li>
* When used with the <code>img</code> tag, it base64 encodes the image it found to make it visible in the
* email.
* When used with the <code>img</code> tag, it base64 encodes the image it found
* to make it visible in the email.
* </li>
* </ul>
*
* @author <a href="https://github.com/rahulsom">Rahul Somasunderam</a>
*/
public class CssInliner {

public static final String CSS_STYLE = "cssstyle";
public static final String STYLE_ATTR = "style";
public static final String STYLE_TAG = "style";
public static final String IMG_TAG = "img";
public static final String IMG_SRC_ATTR = "src";
public static final String DATA_INLINE_ATTR = "data-inline";

private static String concatenateProperties(String oldProp, String newProp) {
if (!oldProp.endsWith(";"))
if (!oldProp.endsWith(";")) {
oldProp += ";";
}
return oldProp.trim() + " " + newProp.trim() + ";";
}

Expand All @@ -63,21 +69,28 @@ private String fetchStyles(Document doc) {
}

/**
* Takes an input string representing an html document and processes it with the Css Inliner.
* Takes an input string representing an html document and processes it with
* the Css Inliner.
*
* @param input the html document
* @return the processed html document
*/
public String process(String input) {

Document doc = Jsoup.parse(input);

// check if the user wants to inline the data
Elements elements = doc.getElementsByAttributeValue(DATA_INLINE_ATTR, "true");
if (elements.isEmpty()) {
return input;
}

extractStyles(doc);
applyStyles(doc);
inlineImages(doc);

doc.outputSettings(doc.outputSettings().prettyPrint(false).escapeMode(Entities.EscapeMode.xhtml));
String output = doc.outerHtml();
return output;
return StringEscapeUtils.unescapeHtml(doc.outerHtml());
}

/**
Expand All @@ -88,7 +101,7 @@ public String process(String input) {
private void inlineImages(Document doc) {
Elements allImages = doc.getElementsByTag(IMG_TAG);
for (Element img : allImages) {
if (img.attr("data-inline").equals("true")) {
if (img.attr(DATA_INLINE_ATTR).equals("true")) {
String src = img.attr(IMG_SRC_ATTR);
try {
URL url = new URL(src);
Expand All @@ -109,7 +122,8 @@ private void inlineImages(Document doc) {
}

/**
* Transfers styles from the <code>cssstyle</code> attribute to the <code>style</code> attribute.
* Transfers styles from the <code>cssstyle</code> attribute to the
* <code>style</code> attribute.
*
* @param doc the html document
*/
Expand All @@ -125,8 +139,10 @@ private void applyStyles(Document doc) {
}

/**
* Extracts styles from the stylesheet and applies them to a <code>cssstyle</code> attribute. This is because the
* styles need to be applied sequentially, but before the <code>style</code> defined for the element inline.
* Extracts styles from the stylesheet and applies them to a
* <code>cssstyle</code> attribute. This is because the styles need to be
* applied sequentially, but before the <code>style</code> defined for the
* element inline.
*
* @param doc the html document
*/
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/hudson/plugins/emailext/plugins/EmailTrigger.java
Expand Up @@ -32,6 +32,17 @@ public static DescriptorExtensionList<EmailTrigger, EmailTriggerDescriptor> all(
return Jenkins.getInstance().<EmailTrigger, EmailTriggerDescriptor>getDescriptorList(EmailTrigger.class);
}

public static List<EmailTriggerDescriptor> allWatchable() {
List<EmailTriggerDescriptor> list = new ArrayList<EmailTriggerDescriptor>();
for(EmailTriggerDescriptor d : all()) {
if(d.isWatchable()) {
list.add(d);
}
}

return list;
}

@Deprecated
protected EmailTrigger(boolean sendToList, boolean sendToDevs, boolean sendToRequestor, boolean sendToCulprits, String recipientList, String replyTo, String subject, String body, String attachmentsPattern, int attachBuildLog, String contentType) {
List<RecipientProvider> providers = new ArrayList<RecipientProvider>();
Expand Down
Expand Up @@ -35,6 +35,8 @@ public void addDefaultRecipientProvider(RecipientProvider provider) {
public List<RecipientProvider> getDefaultRecipientProviders() {
return defaultRecipientProviders;
}

public boolean isWatchable() { return true; }

@Deprecated
public boolean getDefaultSendToCulprits() {
Expand All @@ -55,4 +57,5 @@ public boolean getDefaultSendToList() {
public boolean getDefaultSendToRequester() {
return false;
}

}
Expand Up @@ -24,7 +24,6 @@
public abstract class AbstractScriptTrigger extends EmailTrigger {
protected String triggerScript;

@DataBoundConstructor
public AbstractScriptTrigger(List<RecipientProvider> recipientProviders, String recipientList, String replyTo, String subject, String body, String attachmentsPattern, int attachBuildLog, String contentType, String triggerScript) {
super(recipientProviders, recipientList, replyTo, subject, body, attachmentsPattern, attachBuildLog, contentType);
this.triggerScript = triggerScript;
Expand Down Expand Up @@ -100,15 +99,4 @@ private GroovyShell createEngine(AbstractBuild<?, ?> build, TaskListener listene

return shell;
}

public abstract static class DescriptorImpl extends EmailTriggerDescriptor {

public List<RecipientProvider> getDefaultRecipientProviders() {
return new ArrayList<RecipientProvider>() {
{
add(new ListRecipientProvider());
}
};
}
}
}
Expand Up @@ -33,5 +33,10 @@ public static final class DescriptorImpl extends EmailTriggerDescriptor {
public String getDisplayName() {
return TRIGGER_NAME;
}

@Override
public boolean isWatchable() {
return false;
}
}
}
Expand Up @@ -37,5 +37,10 @@ public DescriptorImpl() {
public String getDisplayName() {
return TRIGGER_NAME;
}

@Override
public boolean isWatchable() {
return false;
}
}
}

0 comments on commit bb0053d

Please sign in to comment.