NIHVIVO-2693 Add Freemarker user-defined directive for email and integrate into email messaging framework.

This commit is contained in:
ryounes 2011-06-14 12:34:39 +00:00
parent 9c9f7dfe57
commit 2fcff042e6
9 changed files with 260 additions and 18 deletions

View file

@ -200,7 +200,7 @@ public class UserAccountsEditPage extends UserAccountsPage {
userAccountsDao.updateUserAccount(userAccount);
strategy.notifyUser();
strategy.notifyUser(vreq);
}
public boolean wasPasswordEmailSent() {

View file

@ -47,7 +47,7 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
protected abstract void setAdditionalProperties(UserAccount u);
protected abstract void notifyUser();
protected abstract void notifyUser(VitroRequest vreq);
protected abstract boolean wasPasswordEmailSent();
@ -57,7 +57,8 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
private static class EmailStrategy extends UserAccountsEditPageStrategy {
private static final String PARAMETER_RESET_PASSWORD = "resetPassword";
private static final String EMAIL_TEMPLATE = "userAccounts-resetPasswordEmail.ftl";
public static final String RESET_PASSWORD_URL = "/accounts/resetPassword";
private boolean resetPassword;
@ -94,7 +95,7 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
}
@Override
protected void notifyUser() {
protected void notifyUser(VitroRequest vreq) {
if (!resetPassword) {
return;
}
@ -102,16 +103,21 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
Map<String, Object> body = new HashMap<String, Object>();
body.put("userAccount", page.getUpdatedAccount());
body.put("passwordLink", buildResetPasswordLink());
body.put("subjectLine", "Reset password request");
//body.put("subjectLine", "Reset password request");
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, page.getUpdatedAccount().getEmailAddress());
email.setSubject("Reset password request");
email.setHtmlTemplate("userAccounts-resetPasswordEmail-html.ftl");
email.setTextTemplate("userAccounts-resetPasswordEmail-text.ftl");
email.setBodyMap(body);
email.send();
vreq.setAttribute("email", email);
email.processTemplate(vreq, EMAIL_TEMPLATE, body);
//email.setSubject("Reset password request");
//email.setHtmlTemplate("userAccounts-resetPasswordEmail-html.ftl");
//email.setTextTemplate("userAccounts-resetPasswordEmail-text.ftl");
//email.setBodyMap(body);
//email.send();
sentEmail = true;
}
@ -193,7 +199,7 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
}
@Override
protected void notifyUser() {
protected void notifyUser(VitroRequest vreq) {
// Do nothing.
}

View file

@ -306,11 +306,18 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
*/
public static Map<String, Object> getDirectives() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("dump", new freemarker.ext.dump.DumpDirective());
map.put("dumpAll", new freemarker.ext.dump.DumpAllDirective());
map.put("help", new freemarker.ext.dump.HelpDirective());
map.putAll(getDirectivesForAllEnvironments());
map.put("url", new edu.cornell.mannlib.vitro.webapp.web.directives.UrlDirective());
map.put("widget", new edu.cornell.mannlib.vitro.webapp.web.directives.WidgetDirective());
return map;
}
public static Map<String, Object> getDirectivesForAllEnvironments() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("dump", new freemarker.ext.dump.DumpDirective());
map.put("dumpAll", new freemarker.ext.dump.DumpAllDirective());
map.put("help", new freemarker.ext.dump.HelpDirective());
return map;
}

View file

@ -2,6 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.email;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
@ -27,9 +29,14 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper.TemplateProcessingException;
import freemarker.core.Environment;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* A framework that makes it simpler to send email messages with a body built
@ -146,6 +153,69 @@ public class FreemarkerEmailMessage {
.unmodifiableMap(new HashMap<String, Object>(body));
}
}
public void processTemplate(VitroRequest vreq, String templateName, Map<String, Object> map) {
vreq.setAttribute("email", this);
map.putAll(FreemarkerHttpServlet.getDirectivesForAllEnvironments());
map.put("email", new edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective());
try {
Template template = config.getTemplate(templateName);
StringWriter writer = new StringWriter();
Environment env = template.createProcessingEnvironment(map, writer);
env.setCustomAttribute("request", vreq);
env.process();
} catch (TemplateException e) {
log.error(e, e);
} catch (IOException e) {
log.error(e, e);
}
}
public void send(String subject, String html, String text) {
try {
MimeMessage msg = new MimeMessage(session);
msg.setReplyTo(new Address[] { replyToAddress });
if (fromAddress == null) {
msg.addFrom(new Address[] { replyToAddress });
} else {
msg.addFrom(new Address[] { fromAddress });
}
for (Recipient recipient : recipients) {
msg.addRecipient(recipient.type, recipient.address);
}
msg.setSubject(subject);
if (html.isEmpty()) {
if (html.isEmpty()) {
log.error("Message has neither text body nor HTML body");
} else {
msg.setContent(html, "text/html");
}
} else {
if (html.isEmpty()) {
msg.setContent(text, "text/plain");
} else {
MimeMultipart content = new MimeMultipart("alternative");
addBodyPart(content, text, "text/plain");
addBodyPart(content, html, "text/html");
msg.setContent(content);
}
}
msg.setSentDate(new Date());
Transport.send(msg);
} catch (MessagingException e) {
log.error("Failed to send message.", e);
}
}
public void send() {
String textBody = figureMessageBody(textTemplateName);

View file

@ -0,0 +1,100 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.directives;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
import freemarker.core.Environment;
import freemarker.template.SimpleScalar;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
public class EmailDirective extends BaseTemplateDirectiveModel {
private static final Log log = LogFactory.getLog(EmailDirective.class);
@Override
public void execute(Environment env, Map params, TemplateModel[] loopVars,
TemplateDirectiveBody body) throws TemplateException, IOException {
Object o = params.get("subject");
if (o == null) {
throw new TemplateModelException(
"The email directive requires a value for parameter 'subject'.");
}
if (! ( o instanceof SimpleScalar)) {
throw new TemplateModelException(
"The email directive requires a string value for parameter 'subject'.");
}
String subject = o.toString();
o = params.get("html");
if (o == null) {
throw new TemplateModelException(
"The email directive requires a value for parameter 'html'.");
}
if (! ( o instanceof SimpleScalar)) {
throw new TemplateModelException(
"The email directive requires a string value for parameter 'html'.");
}
String html = o.toString();
o = params.get("text");
if (o == null) {
throw new TemplateModelException(
"The email directive requires a value for parameter 'text'.");
}
if (! ( o instanceof SimpleScalar)) {
throw new TemplateModelException(
"The email directive requires a string value for parameter 'text'.");
}
String text = o.toString();
HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request");
o = (FreemarkerEmailMessage) request.getAttribute("email");
if ( o == null) {
throw new TemplateModelException(
"No email object found in the request.");
}
if ( ! (o instanceof FreemarkerEmailMessage)) {
throw new TemplateModelException(
"Invalid value for request email attribute");
}
FreemarkerEmailMessage email = (FreemarkerEmailMessage) o;
email.send(subject, html, text);
}
@Override
public Map<String, Object> help(String name) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put("effect", "Create an email message from the parameters set in the invoking template.");
Map<String, String> params = new HashMap<String, String>();
params.put("subject", "email subject");
params.put("html", "HTML version of email message");
params.put("text", "Plain text version of email message");
map.put("parameters", params);
List<String> examples = new ArrayList<String>();
examples.add("&lt;email subject=\"Password reset confirmation\" html=html text=text&gt;");
map.put("examples", examples);
return map;
}
}

View file

@ -15,6 +15,7 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import freemarker.core.Environment;
import freemarker.template.SimpleScalar;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
@ -44,12 +45,19 @@ public class UrlDirective extends BaseTemplateDirectiveModel {
"The url directive doesn't allow nested content.");
}
String path = params.get("path").toString();
if (path == null) {
Object o = params.get("path");
if (o == null) {
throw new TemplateModelException(
"The url directive requires a value for parameter 'path'.");
}
if (! ( o instanceof SimpleScalar)) {
throw new TemplateModelException(
"The url directive requires a string value for parameter 'path'.");
}
String path = o.toString();
if (!path.startsWith("/")) {
throw new TemplateModelException(
"The url directive requires that the value of parameter 'path' is an absolute path starting with '/'.");
@ -60,6 +68,7 @@ public class UrlDirective extends BaseTemplateDirectiveModel {
out.write(url);
}
@Override
public Map<String, Object> help(String name) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
@ -77,6 +86,5 @@ public class UrlDirective extends BaseTemplateDirectiveModel {
return map;
}
}

View file

@ -94,6 +94,7 @@ public class WidgetDirective extends BaseTemplateDirectiveModel {
}
@Override
public Map<String, Object> help(String name) {
Map<String, Object> map = new LinkedHashMap<String, Object>();