001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * bstefanescu 011 */ 012package org.nuxeo.ecm.automation.core.mail; 013 014import java.io.File; 015import java.io.FileInputStream; 016import java.io.IOException; 017import java.io.StringReader; 018import java.io.StringWriter; 019import java.io.Writer; 020import java.net.URL; 021import java.util.List; 022import java.util.Properties; 023import java.util.concurrent.ConcurrentHashMap; 024import java.util.concurrent.ConcurrentMap; 025 026import javax.activation.DataHandler; 027import javax.mail.MessagingException; 028import javax.mail.internet.MimeBodyPart; 029import javax.mail.internet.MimeMultipart; 030 031import org.apache.commons.logging.Log; 032import org.apache.commons.logging.LogFactory; 033import org.nuxeo.ecm.core.api.Blob; 034import org.nuxeo.ecm.platform.rendering.api.RenderingException; 035import org.nuxeo.ecm.platform.rendering.api.ResourceLocator; 036import org.nuxeo.ecm.platform.rendering.fm.FreemarkerEngine; 037import org.nuxeo.runtime.api.Framework; 038 039import freemarker.core.Environment; 040import freemarker.template.Template; 041import freemarker.template.TemplateException; 042 043/** 044 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 045 */ 046public class Composer { 047 048 private static final Log log = LogFactory.getLog(Composer.class); 049 050 protected final FreemarkerEngine engine; 051 052 protected Mailer mailer; 053 054 // FIXME: don't put URLs in Maps, this is a serious performance issue. 055 protected final ConcurrentMap<String, URL> urls; 056 057 public Composer() { 058 this(null); 059 } 060 061 public Composer(Mailer mailer) { 062 urls = new ConcurrentHashMap<String, URL>(); 063 if (mailer == null) { 064 this.mailer = createMailer(); 065 } else { 066 this.mailer = mailer; 067 } 068 engine = new FreemarkerEngine(); 069 engine.setResourceLocator(new ResourceLocator() { 070 @Override 071 public URL getResourceURL(String key) { 072 return urls.get(key); 073 } 074 075 @Override 076 public File getResourceFile(String key) { 077 return null; 078 } 079 }); 080 } 081 082 protected Mailer createMailer() { 083 // first try the local configuration 084 org.nuxeo.common.Environment env = org.nuxeo.common.Environment.getDefault(); 085 if (env != null) { 086 File file = new File(env.getConfig(), "mail.properties"); 087 if (file.isFile()) { 088 Properties p = new Properties(); 089 try { 090 FileInputStream in = new FileInputStream(file); 091 try { 092 p.load(in); 093 mailer = new Mailer(p); 094 } finally { 095 in.close(); 096 } 097 } catch (IOException e) { 098 log.error("Failed to load mail properties", e); 099 } 100 } 101 } 102 // second try using JNDI 103 if (mailer == null) { 104 String name = Framework.getProperty("jndi.java.mail", "java:/Mail"); 105 mailer = new Mailer(name); 106 } 107 return mailer; 108 } 109 110 public void registerTemplate(URL url) { 111 urls.put(url.toExternalForm(), url); 112 } 113 114 public void unregisterTemplate(URL url) { 115 urls.remove(url.toExternalForm()); 116 } 117 118 public void unregisterAllTemplates() { 119 urls.clear(); 120 } 121 122 public Mailer getMailer() { 123 return mailer; 124 } 125 126 public FreemarkerEngine getEngine() { 127 return engine; 128 } 129 130 public void render(String template, Object ctx, Writer writer) throws RenderingException { 131 engine.render(template, ctx, writer); 132 } 133 134 public void render(URL template, Object ctx, Writer writer) throws RenderingException { 135 String key = template.toExternalForm(); 136 urls.putIfAbsent(key, template); 137 engine.render(key, ctx, writer); 138 } 139 140 public String render(URL template, Object ctx) throws RenderingException { 141 String key = template.toExternalForm(); 142 urls.putIfAbsent(key, template); 143 StringWriter writer = new StringWriter(); 144 engine.render(key, ctx, writer); 145 return writer.toString(); 146 } 147 148 public String render(String templateContent, Object ctx) throws TemplateException, IOException { 149 StringReader reader = new StringReader(templateContent); 150 Template temp = new Template("@inline", reader, engine.getConfiguration(), "UTF-8"); 151 StringWriter writer = new StringWriter(); 152 Environment env = temp.createProcessingEnvironment(ctx, writer, engine.getObjectWrapper()); 153 env.process(); 154 return writer.toString(); 155 } 156 157 public Mailer.Message newMessage() { 158 return mailer.newMessage(); 159 } 160 161 public Mailer.Message newTextMessage(URL template, Object ctx) throws RenderingException, MessagingException { 162 Mailer.Message msg = mailer.newMessage(); 163 msg.setText(render(template, ctx), "UTF-8"); 164 return msg; 165 } 166 167 public Mailer.Message newTextMessage(String templateContent, Object ctx) throws RenderingException, 168 MessagingException, TemplateException, IOException { 169 Mailer.Message msg = mailer.newMessage(); 170 msg.setText(render(templateContent, ctx), "UTF-8"); 171 return msg; 172 } 173 174 public Mailer.Message newHtmlMessage(URL template, Object ctx) throws RenderingException, MessagingException { 175 Mailer.Message msg = mailer.newMessage(); 176 msg.setContent(render(template, ctx), "text/html; charset=utf-8"); 177 return msg; 178 } 179 180 public Mailer.Message newHtmlMessage(String templateContent, Object ctx) throws MessagingException, 181 TemplateException, IOException { 182 Mailer.Message msg = mailer.newMessage(); 183 msg.setContent(render(templateContent, ctx), "text/html; charset=utf-8"); 184 return msg; 185 } 186 187 public Mailer.Message newMixedMessage(String templateContent, Object ctx, String textType, List<Blob> attachments) 188 throws TemplateException, IOException, MessagingException { 189 if (textType == null) { 190 textType = "plain"; 191 } 192 Mailer.Message msg = mailer.newMessage(); 193 MimeMultipart mp = new MimeMultipart(); 194 MimeBodyPart body = new MimeBodyPart(); 195 String result = render(templateContent, ctx); 196 body.setText(result, "UTF-8", textType); 197 mp.addBodyPart(body); 198 for (Blob blob : attachments) { 199 MimeBodyPart a = new MimeBodyPart(); 200 a.setDataHandler(new DataHandler(new BlobDataSource(blob))); 201 a.setFileName(blob.getFilename()); 202 mp.addBodyPart(a); 203 } 204 msg.setContent(mp); 205 return msg; 206 } 207 208}