1 package com.ozacc.mail.impl;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.StringReader;
7 import java.io.StringWriter;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11
12 import org.apache.commons.logging.Log;
13 import org.apache.commons.logging.LogFactory;
14 import org.apache.velocity.VelocityContext;
15 import org.apache.velocity.app.Velocity;
16 import org.apache.velocity.exception.MethodInvocationException;
17 import org.apache.velocity.exception.ParseErrorException;
18 import org.apache.velocity.exception.ResourceNotFoundException;
19 import org.apache.velocity.runtime.log.LogSystem;
20 import org.jdom.Document;
21 import org.jdom.Element;
22 import org.jdom.JDOMException;
23 import org.jdom.input.SAXBuilder;
24 import org.jdom.output.XMLOutputter;
25
26 import com.ozacc.mail.Mail;
27 import com.ozacc.mail.MailBuildException;
28 import com.ozacc.mail.VelocityMailBuilder;
29
30 /***
31 * <a href="http://www.jdom.org/">JDOM</a>¤òÍøÍѤ·¤ÆXML¥Õ¥¡¥¤¥?¤«¤éMail¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤¹¤?¥¯¥é¥¹¡£
32 * <p>
33 * ¥½¡¼¥¹XML¤òÆÉ¤ß¹?¤àºÝ¤Ë¡¢DTD¥Ð¥?¥Ç¡¼¥·¥ç¥ó¤¬¼Â¹Ô¤µ¤?¤Þ¤¹¤Î¤ÇÂÅÅö¤ÊXML¥Ç¡¼¥¿(Valid XML Document)¤Ç¤Ê¤±¤?¤Ð¤¤¤±¤Þ¤»¤ó¡£
34 *
35 * @since 1.0
36 *
37 * @author Tomohiro Otsuka
38 * @version $Id: JDomXMLMailBuilder.java,v 1.11 2004/10/22 00:50:18 otsuka Exp $
39 */
40 public class JDomXMLMailBuilder implements VelocityMailBuilder {
41
42 private static Log log = LogFactory.getLog(JDomXMLMailBuilder.class);
43
44 private LogSystem velocityLogSystem = new VelocityLogSystem();
45
46 private boolean cacheEnabled = false;
47
48 private Map templateCache = new HashMap();
49
50 /***
51 * ¥³¥ó¥¹¥È¥é¥¯¥¿¡£
52 */
53 public JDomXMLMailBuilder() {}
54
55 /***
56 * »ØÄꤵ¤?¤¿¥¯¥é¥¹¥Ñ¥¹¾å¤ÎXML¥Õ¥¡¥¤¥?¤«¤éMail¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤·¤Þ¤¹¡£
57 *
58 * @param classPath ¥á¡¼¥?ÆâÍÆ¤òµ½Ò¤·¤¿XML¥Õ¥¡¥¤¥?¤Î¥Ñ¥¹
59 * @return À¸À®¤µ¤?¤¿Mail¥¤¥ó¥¹¥¿¥ó¥¹
60 * @throws MailBuildException Mail¥¤¥ó¥¹¥¿¥ó¥¹¤ÎÀ¸À®¤Ë¼ºÇÔ¤·¤¿¾?¹?
61 */
62 public Mail buildMail(String classPath) throws MailBuildException {
63 Document doc = getDocumentFromClassPath(classPath);
64 return build(doc);
65 }
66
67 /***
68 * »ØÄꤵ¤?¤¿¥¯¥é¥¹¥Ñ¥¹¾å¤ÎXML¥Õ¥¡¥¤¥?¤«¤éMail¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤·¤Þ¤¹¡£
69 * »ØÄꤵ¤?¤¿VelocityContext¤ò»È¤Ã¤Æ¡¢XML¥Õ¥¡¥¤¥?¤ÎÆâÍÆ¤òưŪ¤ËÀ¸À®¤Ç¤¤Þ¤¹¡£
70 *
71 * @param classPath ¥á¡¼¥?ÆâÍÆ¤òµ½Ò¤·¤¿XML¥Õ¥¡¥¤¥?¤Î¥Ñ¥¹
72 * @param context VelocityContext
73 * @return À¸À®¤µ¤?¤¿Mail¥¤¥ó¥¹¥¿¥ó¥¹
74 * @throws MailBuildException Mail¥¤¥ó¥¹¥¿¥ó¥¹¤ÎÀ¸À®¤Ë¼ºÇÔ¤·¤¿¾?¹?
75 */
76 public Mail buildMail(String classPath, VelocityContext context) throws MailBuildException {
77 String templateXmlText;
78 if (!hasTemplateCache(classPath)) {
79 Document doc = getDocumentFromClassPath(classPath);
80 XMLOutputter output = new XMLOutputter();
81 templateXmlText = output.outputString(doc);
82 putTemplateCache(classPath, templateXmlText);
83 } else {
84 templateXmlText = getTemplateCache(classPath);
85 }
86
87 try {
88 return build(templateXmlText, context);
89 } catch (Exception e) {
90 throw new MailBuildException("¥á¡¼¥?¤ÎÀ¸À®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿¡£", e);
91 }
92 }
93
94 /***
95 * »ØÄꤵ¤?¤¿XML¥Õ¥¡¥¤¥?¤«¤éMail¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤·¤Þ¤¹¡£
96 *
97 * @param file ¥á¡¼¥?ÆâÍÆ¤òµ½Ò¤·¤¿XML¥Õ¥¡¥¤¥?
98 * @return À¸À®¤µ¤?¤¿Mail¥¤¥ó¥¹¥¿¥ó¥¹
99 * @throws MailBuildException Mail¥¤¥ó¥¹¥¿¥ó¥¹¤ÎÀ¸À®¤Ë¼ºÇÔ¤·¤¿¾?¹?
100 */
101 public Mail buildMail(File file) throws MailBuildException {
102 Document doc = getDocumentFromFile(file);
103 return build(doc);
104 }
105
106 /***
107 * »ØÄꤵ¤?¤¿XML¥Õ¥¡¥¤¥?¤«¤éMail¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤·¤Þ¤¹¡£
108 * »ØÄꤵ¤?¤¿VelocityContext¤ò»È¤Ã¤Æ¡¢XML¥Õ¥¡¥¤¥?¤ÎÆâÍÆ¤òưŪ¤ËÀ¸À®¤Ç¤¤Þ¤¹¡£
109 *
110 * @param file ¥á¡¼¥?ÆâÍÆ¤òµ½Ò¤·¤¿XML¥Õ¥¡¥¤¥?
111 * @param context VelocityContext
112 * @return À¸À®¤µ¤?¤¿Mail¥¤¥ó¥¹¥¿¥ó¥¹
113 * @throws MailBuildException Mail¥¤¥ó¥¹¥¿¥ó¥¹¤ÎÀ¸À®¤Ë¼ºÇÔ¤·¤¿¾?¹?
114 */
115 public Mail buildMail(File file, VelocityContext context) throws MailBuildException {
116 String templateXmlText;
117 if (!hasTemplateCache(file.getAbsolutePath())) {
118 Document doc = getDocumentFromFile(file);
119 XMLOutputter output = new XMLOutputter();
120 templateXmlText = output.outputString(doc);
121 putTemplateCache(file.getAbsolutePath(), templateXmlText);
122 } else {
123 templateXmlText = getTemplateCache(file.getAbsolutePath());
124 }
125
126 try {
127 return build(templateXmlText, context);
128 } catch (Exception e) {
129 throw new MailBuildException("¥á¡¼¥?¤ÎÀ¸À®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿¡£", e);
130 }
131 }
132
133 /***
134 * »ØÄꤵ¤?¤¿¥¯¥é¥¹¥Ñ¥¹¾å¤Î¥Õ¥¡¥¤¥?¤òÆÉ¤ß¹?¤ó¤Ç¡¢XML¥É¥¥å¥á¥ó¥È¤òÀ¸À®¤·¤Þ¤¹¡£
135 *
136 * @param classPath
137 * @return JDOM Document
138 */
139 private Document getDocumentFromClassPath(String classPath) throws MailBuildException {
140 InputStream is = getClass().getResourceAsStream(classPath);
141 SAXBuilder builder = new SAXBuilder(true);
142 builder.setEntityResolver(new DTDEntityResolver());
143 Document doc;
144 try {
145 doc = builder.build(is);
146 is.close();
147 } catch (JDOMException e) {
148 throw new MailBuildException("XML¤Î¥Ñ¡¼¥¹¤Ë¼ºÇÔ¤·¤Þ¤·¤¿¡£" + e.getMessage(), e);
149 } catch (IOException e) {
150 throw new MailBuildException("XML¥Õ¥¡¥¤¥?¤ÎÆÉ¤ß¹?¤ß¤Ë¼ºÇÔ¤·¤Þ¤·¤¿¡£", e);
151 }
152 return doc;
153 }
154
155 /***
156 * »ØÄꤵ¤?¤¿¥Õ¥¡¥¤¥?¤òÆÉ¤ß¹?¤ó¤Ç¡¢XML¥É¥¥å¥á¥ó¥È¤òÀ¸À®¤·¤Þ¤¹¡£
157 *
158 * @param file
159 * @return JDOM Document
160 */
161 private Document getDocumentFromFile(File file) {
162 SAXBuilder builder = new SAXBuilder(true);
163 builder.setEntityResolver(new DTDEntityResolver());
164 Document doc;
165 try {
166 doc = builder.build(file);
167 } catch (JDOMException e) {
168 throw new MailBuildException("XML¤Î¥Ñ¡¼¥¹¤Ë¼ºÇÔ¤·¤Þ¤·¤¿¡£" + e.getMessage(), e);
169 } catch (IOException e) {
170 throw new MailBuildException("XML¥Õ¥¡¥¤¥?¤ÎÆÉ¤ß¹?¤ß¤Ë¼ºÇÔ¤·¤Þ¤·¤¿¡£", e);
171 }
172 return doc;
173 }
174
175 /***
176 * XML¥É¥¥å¥á¥ó¥È¤«¤éMail¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤·¤Þ¤¹¡£
177 *
178 * @param doc
179 * @return Mail
180 */
181 private Mail build(Document doc) {
182 Element root = doc.getRootElement();
183
184 Mail mail = new Mail();
185 setFrom(root, mail);
186 setRecipients(root, mail);
187 setSubject(root, mail);
188 setBody(root, mail);
189 setReplyTo(root, mail);
190 setReturnPath(root, mail);
191
192 setHtml(root, mail);
193
194 return mail;
195 }
196
197 /***
198 * VelocityContext¤ÈXML¥É¥¥å¥á¥ó¥È¤ò¥Þ¡¼¥¸¤µ¤»¡¢Mail¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤·¤Þ¤¹¡£
199 *
200 * @param context
201 * @param doc
202 * @return Mail
203 *
204 * @throws Exception
205 * @throws ParseErrorException
206 * @throws MethodInvocationException
207 * @throws ResourceNotFoundException
208 * @throws IOException
209 * @throws JDOMException
210 */
211 private Mail build(String templateText, VelocityContext context) throws Exception,
212 ParseErrorException,
213 MethodInvocationException,
214 ResourceNotFoundException,
215 IOException, JDOMException {
216 if (log.isDebugEnabled()) {
217 log.debug("Source XML Mail Data\n" + templateText);
218 }
219
220 Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, velocityLogSystem);
221 Velocity.init();
222 StringWriter w = new StringWriter();
223 Velocity.evaluate(context, w, "XML Mail Data", templateText);
224
225 if (log.isDebugEnabled()) {
226 String newXmlContent = w.toString();
227 log.debug("VelocityContext-merged XML Mail Data\n" + newXmlContent);
228 }
229
230 StringReader reader = new StringReader(w.toString());
231 SAXBuilder builder = new SAXBuilder(true);
232 builder.setEntityResolver(new DTDEntityResolver());
233 Document doc2 = builder.build(reader);
234
235 return build(doc2);
236 }
237
238 /***
239 * @param root
240 * @param mail
241 */
242 private void setReturnPath(Element root, Mail mail) {
243 Element returnPathElem = root.getChild("returnPath");
244 if (returnPathElem != null && returnPathElem.getAttributeValue("email") != null) {
245 mail.setReturnPath(returnPathElem.getAttributeValue("email"));
246 }
247 }
248
249 /***
250 * @param root
251 * @param mail
252 */
253 private void setReplyTo(Element root, Mail mail) {
254 Element replyToElem = root.getChild("replyTo");
255 if (replyToElem != null && replyToElem.getAttributeValue("email") != null) {
256 mail.setReplyTo(replyToElem.getAttributeValue("email"));
257 }
258 }
259
260 /***
261 * @param root
262 * @param mail
263 */
264 private void setBody(Element root, Mail mail) {
265 Element bodyElem = root.getChild("body");
266 if (bodyElem != null) {
267 mail.setText(bodyElem.getTextTrim());
268 }
269 }
270
271 /***
272 * @param root
273 * @param mail
274 */
275 private void setHtml(Element root, Mail mail) {
276 Element htmlElem = root.getChild("html");
277 if (htmlElem != null) {
278 mail.setHtmlText(htmlElem.getTextTrim());
279 }
280 }
281
282 /***
283 * @param root
284 * @param mail
285 */
286 private void setSubject(Element root, Mail mail) {
287 Element subjectElem = root.getChild("subject");
288 if (subjectElem != null) {
289 mail.setSubject(subjectElem.getTextTrim());
290 }
291 }
292
293 /***
294 * @param root
295 * @param mail
296 */
297 private void setRecipients(Element root, Mail mail) {
298 Element recipientsElem = root.getChild("recipients");
299 if (recipientsElem == null) {
300 return;
301 }
302
303 List recipientElemList = recipientsElem.getChildren();
304 for (int i = 0, max = recipientElemList.size(); i < max; i++) {
305 Element e = (Element)recipientElemList.get(i);
306 if ("to".equals(e.getName())) {
307 if (e.getAttributeValue("email") != null) {
308 if (e.getAttributeValue("name") != null) {
309 mail.addTo(e.getAttributeValue("email"), e.getAttributeValue("name"));
310 } else {
311 mail.addTo(e.getAttributeValue("email"));
312 }
313 }
314 } else if ("cc".equals(e.getName())) {
315 if (e.getAttributeValue("email") != null) {
316 if (e.getAttributeValue("name") != null) {
317 mail.addCc(e.getAttributeValue("email"), e.getAttributeValue("name"));
318 } else {
319 mail.addCc(e.getAttributeValue("email"));
320 }
321 }
322 } else {
323 if (e.getAttributeValue("email") != null) {
324 mail.addBcc(e.getAttributeValue("email"));
325 }
326 }
327 }
328 }
329
330 /***
331 * @param root
332 * @param mail
333 */
334 private void setFrom(Element root, Mail mail) {
335 Element fromElem = root.getChild("from");
336 if (fromElem != null && fromElem.getAttributeValue("email") != null) {
337 if (fromElem.getAttributeValue("name") != null) {
338 mail.setFrom(fromElem.getAttributeValue("email"), fromElem
339 .getAttributeValue("name"));
340 } else {
341 mail.setFrom(fromElem.getAttributeValue("email"));
342 }
343 }
344 }
345
346 /***
347 * @see com.ozacc.mail.VelocityMailBuilder#clearCache()
348 */
349 public synchronized void clearCache() {
350 log.debug("¥Æ¥ó¥×¥?¡¼¥È¥¥ã¥Ã¥·¥å¤ò¥¯¥?¥¢¤·¤Þ¤¹¡£");
351 templateCache.clear();
352 }
353
354 /***
355 * @see com.ozacc.mail.VelocityMailBuilder#isCacheEnabled()
356 */
357 public boolean isCacheEnabled() {
358 return cacheEnabled;
359 }
360
361 /***
362 * @see com.ozacc.mail.VelocityMailBuilder#setCacheEnabled(boolean)
363 */
364 public void setCacheEnabled(boolean cacheEnabled) {
365 if (!cacheEnabled) {
366 clearCache();
367 }
368 this.cacheEnabled = cacheEnabled;
369 }
370
371 private boolean hasTemplateCache(String key) {
372 if (cacheEnabled) {
373 return templateCache.containsKey(key);
374 }
375 return false;
376 }
377
378 private void putTemplateCache(String key, String templateXmlText) {
379 if (cacheEnabled) {
380 log.debug("¥Æ¥ó¥×¥?¡¼¥È¤ò¥¥ã¥Ã¥·¥å¤·¤Þ¤¹¡£[key='" + key + "']");
381 templateCache.put(key, templateXmlText);
382 }
383 }
384
385 private String getTemplateCache(String key) {
386 if (hasTemplateCache(key)) {
387 log.debug("¥Æ¥ó¥×¥?¡¼¥È¥¥ã¥Ã¥·¥å¤òÊÖ¤·¤Þ¤¹¡£[key='" + key + "']");
388 return (String)templateCache.get(key);
389 }
390 return null;
391 }
392
393 }