com.ozacc.mail.impl.XMLVelocityMailBuilderImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ozacc-mail Show documentation
Show all versions of ozacc-mail Show documentation
Library to send and receive emails.
The newest version!
package com.ozacc.mail.impl;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.ozacc.mail.Mail;
import com.ozacc.mail.MailBuildException;
import com.ozacc.mail.VelocityMultipleMailBuilder;
/**
* XMLファイルを読み込み、Velocityと連携して動的にメールデータを生成し、そのデータからMailインスタンスを生成するクラス。
*
* @since 1.0.1
* @author Tomohiro Otsuka
* @version $Id: XMLVelocityMailBuilderImpl.java,v 1.4.2.4 2005/01/23 06:13:10 otsuka Exp $
*/
public class XMLVelocityMailBuilderImpl extends XMLMailBuilderImpl implements
VelocityMultipleMailBuilder {
private static Log log = LogFactory.getLog(XMLVelocityMailBuilderImpl.class);
private static String CACHE_KEY_SEPARATOR = "#";
private static String DEFAULT_MAIL_ID = "DEFAULT";
protected String charset = "UTF-8";
protected Map templateCache = new HashMap<>();
private boolean cacheEnabled = false;
protected boolean hasTemplateCache(String key) {
if (cacheEnabled) {
return templateCache.containsKey(key);
}
return false;
}
protected void putTemplateCache(String key, String templateXmlText) {
if (cacheEnabled) {
log.debug("テンプレートをキャッシュします。[key='" + key + "']");
templateCache.put(key, templateXmlText);
}
}
protected String getTemplateCache(String key) {
if (hasTemplateCache(key)) {
log.debug("テンプレートキャッシュを返します。[key='" + key + "']");
return templateCache.get(key);
}
return null;
}
/**
* @see com.ozacc.mail.VelocityMailBuilder#clearCache()
*/
public synchronized void clearCache() {
log.debug("テンプレートキャッシュをクリアします。");
templateCache.clear();
}
/**
* @see com.ozacc.mail.VelocityMailBuilder#isCacheEnabled()
*/
public boolean isCacheEnabled() {
return cacheEnabled;
}
/**
* @see com.ozacc.mail.VelocityMailBuilder#setCacheEnabled(boolean)
*/
public void setCacheEnabled(boolean cacheEnabled) {
if (!cacheEnabled) {
clearCache();
}
this.cacheEnabled = cacheEnabled;
}
/**
* @see com.ozacc.mail.VelocityMailBuilder#buildMail(java.lang.String, org.apache.velocity.VelocityContext)
*/
public Mail buildMail(String classPath, VelocityContext context) throws MailBuildException {
String cacheKey = classPath + CACHE_KEY_SEPARATOR + DEFAULT_MAIL_ID;
String templateXmlText;
if (!hasTemplateCache(cacheKey)) {
Document doc;
try {
// Velocityマージ前のXMLではコメントを許可する
doc = getDocumentFromClassPath(classPath, false);
} catch (SAXException e) {
throw new MailBuildException("XMLのパースに失敗しました。" + e.getMessage(), e);
} catch (IOException e) {
throw new MailBuildException("XMLファイルの読み込みに失敗しました。", e);
}
templateXmlText = convertDocumentIntoString(doc.getDocumentElement());
putTemplateCache(cacheKey, templateXmlText);
} else {
templateXmlText = getTemplateCache(cacheKey);
}
try {
return build(templateXmlText, context);
} catch (Exception e) {
throw new MailBuildException("メールの生成に失敗しました。", e);
}
}
/**
* @see com.ozacc.mail.VelocityMailBuilder#buildMail(java.io.File, org.apache.velocity.VelocityContext)
*/
public Mail buildMail(File file, VelocityContext context) throws MailBuildException {
String cacheKey = file.getAbsolutePath() + CACHE_KEY_SEPARATOR + DEFAULT_MAIL_ID;
String templateXmlText;
if (!hasTemplateCache(cacheKey)) {
Document doc;
try {
// Velocityマージ前のXMLではコメントを許可する
doc = getDocumentFromFile(file, false);
} catch (SAXException e) {
throw new MailBuildException("XMLのパースに失敗しました。" + e.getMessage(), e);
} catch (IOException e) {
throw new MailBuildException("XMLファイルの読み込みに失敗しました。", e);
}
templateXmlText = convertDocumentIntoString(doc.getDocumentElement());
putTemplateCache(cacheKey, templateXmlText);
} else {
templateXmlText = getTemplateCache(cacheKey);
}
try {
return build(templateXmlText, context);
} catch (Exception e) {
throw new MailBuildException("メールの生成に失敗しました。", e);
}
}
/**
* メールデータをVelocityContextとマージして生成されたXMLからMailインスタンスを生成します。
*
* @param templateXmlText メールデータのテンプレート
* @param context テンプレートにマージする内容を格納したVelocityContext
* @return VelocityContextをテンプレートにマージして生成されたXMLから生成されたMailインスタンス
* @throws TransformerFactoryConfigurationError
* @throws Exception
* @throws ParseErrorException
* @throws MethodInvocationException
* @throws ResourceNotFoundException
* @throws IOException
*/
protected synchronized Mail build(String templateXmlText, VelocityContext context)
throws TransformerFactoryConfigurationError,
Exception,
ParseErrorException,
MethodInvocationException,
ResourceNotFoundException,
IOException {
if (log.isDebugEnabled()) {
log.debug("Source XML Mail Data\n" + templateXmlText);
}
Velocity.init();
StringWriter w = new StringWriter();
Velocity.evaluate(context, w, "XML Mail Data", templateXmlText);
StringReader reader = new StringReader(w.toString());
DocumentBuilder db = createDocumentBuilder();
InputSource source = new InputSource(reader);
Document newDoc = db.parse(source);
if (log.isDebugEnabled()) {
String newXmlContent = convertDocumentIntoString(newDoc.getDocumentElement());
log.debug("VelocityContext-merged XML Mail Data\n" + newXmlContent);
}
return buildMail(newDoc.getDocumentElement());
}
/**
* 指定されたDOM Documentを文字列に変換します。
*
* @param mailElement
* @return XMLドキュメントの文字列
* @throws TransformerFactoryConfigurationError
*/
protected String convertDocumentIntoString(Element mailElement)
throws TransformerFactoryConfigurationError {
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer t;
try {
t = tf.newTransformer();
} catch (TransformerConfigurationException e) {
throw new MailBuildException(e.getMessage(), e);
}
t.setOutputProperties(getOutputProperties());
DOMSource source = new DOMSource(mailElement);
StringWriter w = new StringWriter();
StreamResult result = new StreamResult(w);
try {
t.transform(source, result);
} catch (TransformerException e) {
throw new MailBuildException(e.getMessage(), e);
}
return w.toString();
}
/**
* 出力プロパティを生成。
* @return 出力プロパティを設定したPropertiesインスタンス
*/
protected Properties getOutputProperties() {
Properties p = new Properties();
p.put(OutputKeys.ENCODING, charset);
p.put(OutputKeys.DOCTYPE_PUBLIC, Mail.DOCTYPE_PUBLIC);
p.put(OutputKeys.DOCTYPE_SYSTEM, Mail.DOCTYPE_SYSTEM);
return p;
}
/**
* @see com.ozacc.mail.VelocityMultipleMailBuilder#buildMail(java.lang.String, org.apache.velocity.VelocityContext, java.lang.String)
*/
public Mail buildMail(String classPath, VelocityContext context, String mailId)
throws MailBuildException {
if (mailId == null || "".equals(mailId)) {
throw new IllegalArgumentException("メールIDが指定されていません。");
}
String cacheKey = classPath + CACHE_KEY_SEPARATOR + mailId;
String templateXmlText;
if (!hasTemplateCache(cacheKey)) {
Document doc;
try {
// Velocityマージ前のXMLではコメントを許可する
doc = getDocumentFromClassPath(classPath, false);
} catch (SAXException e) {
throw new MailBuildException("XMLのパースに失敗しました。" + e.getMessage(), e);
} catch (IOException e) {
throw new MailBuildException("XMLファイルの読み込みに失敗しました。", e);
}
if (Mail.DOCTYPE_PUBLIC.equals(doc.getDoctype().getPublicId())) {
throw new MailBuildException("指定されたクラスパスのXMLはシングルメールテンプレートです。[classPath='"
+ classPath + "']");
}
templateXmlText = getAndCacheTemplateText(doc, mailId, cacheKey);
} else {
templateXmlText = getTemplateCache(cacheKey);
}
try {
return build(templateXmlText, context);
} catch (Exception e) {
throw new MailBuildException("メールの生成に失敗しました。", e);
}
}
private String getAndCacheTemplateText(Document doc, String mailId, String cacheKey)
throws TransformerFactoryConfigurationError {
Element mailElem = doc.getElementById(mailId);
if (mailElem == null) {
throw new MailBuildException("指定されたID[" + mailId + "]のメールデータは見つかりませんでした。");
}
String templateXmlText = convertDocumentIntoString(mailElem);
putTemplateCache(cacheKey, templateXmlText);
return templateXmlText;
}
/**
* @see com.ozacc.mail.VelocityMultipleMailBuilder#buildMail(java.io.File, org.apache.velocity.VelocityContext, java.lang.String)
*/
public Mail buildMail(File file, VelocityContext context, String mailId)
throws MailBuildException {
if (mailId == null || "".equals(mailId)) {
throw new IllegalArgumentException("メールIDが指定されていません。");
}
String cacheKey = file.getAbsolutePath() + CACHE_KEY_SEPARATOR + mailId;
String templateXmlText;
if (!hasTemplateCache(cacheKey)) {
Document doc;
try {
// Velocityマージ前のXMLではコメントを許可する
doc = getDocumentFromFile(file, false);
} catch (SAXException e) {
throw new MailBuildException("XMLのパースに失敗しました。" + e.getMessage(), e);
} catch (IOException e) {
throw new MailBuildException("XMLファイルの読み込みに失敗しました。", e);
}
if (Mail.DOCTYPE_PUBLIC.equals(doc.getDoctype().getPublicId())) {
throw new MailBuildException("指定されたファイルのXMLはシングルメールテンプレートです。[filePath='"
+ file.getAbsolutePath() + "']");
}
templateXmlText = getAndCacheTemplateText(doc, mailId, cacheKey);
} else {
templateXmlText = getTemplateCache(cacheKey);
}
try {
return build(templateXmlText, context);
} catch (Exception e) {
throw new MailBuildException("メールの生成に失敗しました。", e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy