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}