001: package org.jbpm.mail;
002:
003: import java.io.InputStream;
004: import java.io.Serializable;
005: import java.util.ArrayList;
006: import java.util.Arrays;
007: import java.util.Collection;
008: import java.util.Date;
009: import java.util.HashMap;
010: import java.util.Iterator;
011: import java.util.List;
012: import java.util.Map;
013: import java.util.Properties;
014: import java.util.StringTokenizer;
015:
016: import javax.mail.Message;
017: import javax.mail.Session;
018: import javax.mail.Transport;
019: import javax.mail.internet.InternetAddress;
020: import javax.mail.internet.MimeMessage;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.jbpm.JbpmConfiguration;
025: import org.jbpm.JbpmException;
026: import org.jbpm.graph.def.ActionHandler;
027: import org.jbpm.graph.exe.ExecutionContext;
028: import org.jbpm.jpdl.el.ELException;
029: import org.jbpm.jpdl.el.VariableResolver;
030: import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
031: import org.jbpm.util.ClassLoaderUtil;
032: import org.jbpm.util.XmlUtil;
033:
034: public class Mail implements ActionHandler {
035:
036: private static final long serialVersionUID = 1L;
037:
038: String template = null;
039: String actors = null;
040: String to = null;
041: String subject = null;
042: String text = null;
043:
044: ExecutionContext executionContext = null;
045:
046: public Mail() {
047: }
048:
049: public Mail(String template, String actors, String to,
050: String subject, String text) {
051: this .template = template;
052: this .actors = actors;
053: this .to = to;
054: this .subject = subject;
055: this .text = text;
056: }
057:
058: public void execute(ExecutionContext executionContext) {
059: this .executionContext = executionContext;
060: send();
061: }
062:
063: public List getRecipients() {
064: List recipients = new ArrayList();
065: if (actors != null) {
066: String evaluatedActors = evaluate(actors);
067: List tokenizedActors = tokenize(evaluatedActors);
068: if (tokenizedActors != null) {
069: recipients.addAll(resolveAddresses(tokenizedActors));
070: }
071: }
072: if (to != null) {
073: String resolvedTo = evaluate(to);
074: recipients.addAll(tokenize(resolvedTo));
075: }
076: return recipients;
077: }
078:
079: public String getSubject() {
080: if (subject == null)
081: return null;
082: return evaluate(subject);
083: }
084:
085: public String getText() {
086: if (text == null)
087: return null;
088: return evaluate(text);
089: }
090:
091: public String getFromAddress() {
092: if (JbpmConfiguration.Configs
093: .hasObject("jbpm.mail.from.address")) {
094: return JbpmConfiguration.Configs
095: .getString("jbpm.mail.from.address");
096: }
097: return "jbpm@noreply";
098: }
099:
100: public void send() {
101: if (template != null) {
102: Properties properties = getMailTemplateProperties(template);
103: if (actors == null) {
104: actors = properties.getProperty("actors");
105: }
106: if (to == null) {
107: to = properties.getProperty("to");
108: }
109: if (subject == null) {
110: subject = properties.getProperty("subject");
111: }
112: if (text == null) {
113: text = properties.getProperty("text");
114: }
115: }
116:
117: send(getMailServerProperties(), getFromAddress(),
118: getRecipients(), getSubject(), getText());
119: }
120:
121: public static void send(Properties mailServerProperties,
122: String fromAddress, List recipients, String subject,
123: String text) {
124: if ((recipients == null) || (recipients.isEmpty())) {
125: log.debug("skipping mail because there are no recipients");
126: return;
127: }
128: log.debug("sending email to '" + recipients + "' about '"
129: + subject + "'");
130: Session session = Session.getDefaultInstance(
131: mailServerProperties, null);
132: MimeMessage message = new MimeMessage(session);
133: try {
134: if (fromAddress != null) {
135: message.setFrom(new InternetAddress(fromAddress));
136: }
137: Iterator iter = recipients.iterator();
138: while (iter.hasNext()) {
139: InternetAddress recipient = new InternetAddress(
140: (String) iter.next());
141: message.addRecipient(Message.RecipientType.TO,
142: recipient);
143: }
144: if (subject != null) {
145: message.setSubject(subject);
146: }
147: if (text != null) {
148: message.setText(text);
149: }
150: message.setSentDate(new Date());
151:
152: Transport.send(message);
153: } catch (Exception e) {
154: throw new JbpmException("couldn't send email", e);
155: }
156: }
157:
158: protected List tokenize(String text) {
159: if (text == null) {
160: return null;
161: }
162: List list = new ArrayList();
163: StringTokenizer tokenizer = new StringTokenizer(text, ";:");
164: while (tokenizer.hasMoreTokens()) {
165: list.add(tokenizer.nextToken());
166: }
167: return list;
168: }
169:
170: protected Collection resolveAddresses(List actorIds) {
171: List emailAddresses = new ArrayList();
172: Iterator iter = actorIds.iterator();
173: while (iter.hasNext()) {
174: String actorId = (String) iter.next();
175: AddressResolver addressResolver = (AddressResolver) JbpmConfiguration.Configs
176: .getObject("jbpm.mail.address.resolver");
177: Object resolvedAddresses = addressResolver
178: .resolveAddress(actorId);
179: if (resolvedAddresses != null) {
180: if (resolvedAddresses instanceof String) {
181: emailAddresses.add((String) resolvedAddresses);
182: } else if (resolvedAddresses instanceof Collection) {
183: emailAddresses
184: .addAll((Collection) resolvedAddresses);
185: } else if (resolvedAddresses instanceof String[]) {
186: emailAddresses.addAll(Arrays
187: .asList((String[]) resolvedAddresses));
188: } else {
189: throw new JbpmException(
190: "Address resolver '"
191: + addressResolver
192: + "' returned '"
193: + resolvedAddresses.getClass()
194: .getName()
195: + "' instead of a String, Collection or String-array: "
196: + resolvedAddresses);
197: }
198: }
199: }
200: return emailAddresses;
201: }
202:
203: Properties getMailServerProperties() {
204: Properties mailServerProperties = new Properties();
205:
206: if (JbpmConfiguration.Configs
207: .hasObject("resource.mail.properties")) {
208: String mailServerPropertiesResource = JbpmConfiguration.Configs
209: .getString("resource.mail.properties");
210: try {
211: InputStream mailServerStream = ClassLoaderUtil
212: .getStream(mailServerPropertiesResource);
213: mailServerProperties.load(mailServerStream);
214: } catch (Exception e) {
215: throw new JbpmException(
216: "couldn't get configuration properties for jbpm mail server from resource '"
217: + mailServerPropertiesResource + "'", e);
218: }
219:
220: } else if (JbpmConfiguration.Configs
221: .hasObject("jbpm.mail.smtp.host")) {
222: String smtpServer = JbpmConfiguration.Configs
223: .getString("jbpm.mail.smtp.host");
224: mailServerProperties.put("mail.smtp.host", smtpServer);
225:
226: } else {
227:
228: log.error("couldn't get mail properties");
229: }
230:
231: return mailServerProperties;
232: }
233:
234: static Map templates = null;
235: static Map templateVariables = null;
236:
237: synchronized Properties getMailTemplateProperties(
238: String templateName) {
239: if (templates == null) {
240: templates = new HashMap();
241: String mailTemplatesResource = JbpmConfiguration.Configs
242: .getString("resource.mail.templates");
243: org.w3c.dom.Element mailTemplatesElement = XmlUtil
244: .parseXmlResource(mailTemplatesResource)
245: .getDocumentElement();
246: List mailTemplateElements = XmlUtil.elements(
247: mailTemplatesElement, "mail-template");
248: Iterator iter = mailTemplateElements.iterator();
249: while (iter.hasNext()) {
250: org.w3c.dom.Element mailTemplateElement = (org.w3c.dom.Element) iter
251: .next();
252:
253: Properties templateProperties = new Properties();
254: addTemplateProperty(mailTemplateElement, "actors",
255: templateProperties);
256: addTemplateProperty(mailTemplateElement, "to",
257: templateProperties);
258: addTemplateProperty(mailTemplateElement, "subject",
259: templateProperties);
260: addTemplateProperty(mailTemplateElement, "text",
261: templateProperties);
262:
263: templates.put(mailTemplateElement.getAttribute("name"),
264: templateProperties);
265: }
266:
267: templateVariables = new HashMap();
268: List variableElements = XmlUtil.elements(
269: mailTemplatesElement, "variable");
270: iter = variableElements.iterator();
271: while (iter.hasNext()) {
272: org.w3c.dom.Element variableElement = (org.w3c.dom.Element) iter
273: .next();
274: templateVariables.put(variableElement
275: .getAttribute("name"), variableElement
276: .getAttribute("value"));
277: }
278: }
279: return (Properties) templates.get(templateName);
280: }
281:
282: void addTemplateProperty(org.w3c.dom.Element mailTemplateElement,
283: String property, Properties templateProperties) {
284: org.w3c.dom.Element element = XmlUtil.element(
285: mailTemplateElement, property);
286: if (element != null) {
287: templateProperties.put(property, XmlUtil
288: .getContentText(element));
289: }
290: }
291:
292: String evaluate(String expression) {
293: if (expression == null) {
294: return null;
295: }
296: VariableResolver variableResolver = JbpmExpressionEvaluator
297: .getUsedVariableResolver();
298: if (variableResolver != null) {
299: variableResolver = new MailVariableResolver(
300: templateVariables, variableResolver);
301: }
302: return (String) JbpmExpressionEvaluator.evaluate(expression,
303: executionContext, variableResolver, null);
304: }
305:
306: class MailVariableResolver implements VariableResolver,
307: Serializable {
308: private static final long serialVersionUID = 1L;
309: Map templateVariables = null;
310: VariableResolver variableResolver = null;
311:
312: public MailVariableResolver(Map templateVariables,
313: VariableResolver variableResolver) {
314: this .templateVariables = templateVariables;
315: this .variableResolver = variableResolver;
316: }
317:
318: public Object resolveVariable(String pName) throws ELException {
319: if ((templateVariables != null)
320: && (templateVariables.containsKey(pName))) {
321: return templateVariables.get(pName);
322: }
323: return variableResolver.resolveVariable(pName);
324: }
325: }
326:
327: private static Log log = LogFactory.getLog(Mail.class);
328: }
|