/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springmodules.email.parser.xml;
import java.io.IOException;
import java.util.*;
import javax.mail.internet.InternetAddress;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.StringUtils;
import org.springmodules.email.*;
import org.springmodules.email.parser.EmailParseException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* A SAX based implementation of {@link org.springmodules.email.EmailParser} where the parsed XML defines an email.
*
* @author Uri Boness
*/
public class SaxEmailParser implements EmailParser, ResourceLoaderAware {
private ResourceLoader resourceLoader;
/**
* Constructs a new SaxEmailParser where the {@link DefaultResourceLoader} is used to load the attchment
* resources.
*/
public SaxEmailParser() {
this(new DefaultResourceLoader());
}
/**
* Constructs a new SaxEmailParser with a given {@link ResourceLoader} that is used to load the attchment
* resources.
*
* @param resourceLoader The resource loader that is used to load the attachment resources.
*/
public SaxEmailParser(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
/**
* Parses the given XML resource using SAX parser and returning the parsed {@link Email}.
*
* @param resource The XML resource to parse.
* @return The parsed emaill
* @see EmailParser#parse(Resource)
*/
public Email parse(Resource resource) {
EmailContentHandler handler = new EmailContentHandler();
try {
SAXParserFactory.newInstance().newSAXParser().parse(resource.getInputStream(), handler);
} catch (ParserConfigurationException pce) {
throw new EmailParseException("Could not parse email resource '" + resource.getDescription() + "'", pce);
} catch (SAXException se) {
throw new EmailParseException("Could not parse email resource '" + resource.getDescription() + "'", se);
} catch (IOException ioe) {
throw new EmailParseException("Could not parse email resource '" + resource.getDescription() + "'", ioe);
}
return handler.getEmail();
}
/**
* Sets the resource loader that is used to load the attachment resources.
*
* @param resourceLoader The resource loader that is used to load the attachment resources.
* @see ResourceLoaderAware
*/
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
/**
* A SAX {@link java.net.ContentHandler} that builds an {@link Email} object along the parsing process.
*/
protected class EmailContentHandler extends DefaultHandler {
private Email email = new Email();
private List list = new ArrayList();
private Set set = new HashSet();
private Map map = new HashMap();
private String name;
private StringBuffer buffer = new StringBuffer();
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
String elementName = qName.toLowerCase();
if ("from".equals(elementName) || "reply-to".equals(elementName) || "address".equals(elementName) || "header".equals(elementName)) {
name = attributes.getValue("name");
name = (StringUtils.hasText(name)) ? name : null;
}
else if ("attachment".equals(elementName)) {
name = attributes.getValue("name");
}
}
public void endElement(String uri, String localName, String qName) throws SAXException {
String elementName = qName.toLowerCase();
if ("from".equals(elementName)) {
if (name != null) {
email.setFrom(name, buffer.toString().trim());
} else {
email.setFrom(buffer.toString().trim());
}
buffer = new StringBuffer();
}
else if ("reply-to".equals(elementName)) {
if (name != null) {
email.setReplyTo(name, buffer.toString().trim());
} else {
email.setFrom(buffer.toString().trim());
}
buffer = new StringBuffer();
}
else if ("address".equals(elementName)) {
if (name != null) {
list.add(EmailUtils.createAddress(name, buffer.toString().trim()));
} else {
list.add(EmailUtils.createAddress(buffer.toString().trim()));
}
buffer = new StringBuffer();
}
else if ("to".equals(elementName)) {
email.setTo((InternetAddress[])list.toArray(new InternetAddress[list.size()]));
list = new ArrayList();
}
else if ("cc".equals(elementName)) {
email.setCc((InternetAddress[])list.toArray(new InternetAddress[list.size()]));
list = new ArrayList();
}
else if ("bcc".equals(elementName)) {
email.setBcc((InternetAddress[])list.toArray(new InternetAddress[list.size()]));
list = new ArrayList();
}
else if ("attachments".equals(elementName)) {
email.setAttachments(set);
set = new HashSet();
}
else if ("inline-attachments".equals(elementName)) {
email.setInlineAttachments(set);
set = new HashSet();
}
else if ("attachment".equals(elementName)) {
set.add(new Attachment(name, resourceLoader.getResource(buffer.toString().trim())));
buffer = new StringBuffer();
}
else if ("priority".equals(elementName)) {
email.setPriority(EmailPriority.name(buffer.toString().trim()));
buffer = new StringBuffer();
}
else if ("subject".equals(elementName)) {
email.setSubject(buffer.toString().trim());
buffer = new StringBuffer();
}
else if ("text-body".equals(elementName)) {
email.setTextBody(buffer.toString().trim());
buffer = new StringBuffer();
}
else if ("html-body".equals(elementName)) {
email.setHtmlBody(buffer.toString().trim());
buffer = new StringBuffer();
}
else if ("headers".equals(elementName)) {
email.setHeaders(map);
map = new HashMap();
}
else if ("header".equals(elementName)) {
map.put(name, buffer.toString().trim());
buffer = new StringBuffer();
}
}
public void characters(char ch[], int start, int length) throws SAXException {
buffer.append(ch, start, length);
}
public Email getEmail() {
return email;
}
}
}