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