/* * Copyright 2005-2014 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.springframework.ws.transport.mail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.mail.Address; import javax.mail.Header; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.URLName; import javax.mail.internet.InternetAddress; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.transport.AbstractReceiverConnection; import org.springframework.ws.transport.TransportConstants; import org.springframework.ws.transport.WebServiceConnection; import org.springframework.ws.transport.mail.support.MailTransportUtils; /** * Implementation of {@link WebServiceConnection} that is used for server-side Mail access. Exposes a {@link Message} * request and response message. * * @author Arjen Poutsma * @author Greg Turnquist * @since 1.5.0 */ public class MailReceiverConnection extends AbstractReceiverConnection { private final Message requestMessage; private final Session session; private Message responseMessage; private ByteArrayOutputStream responseBuffer; private String responseContentType; private URLName transportUri; private InternetAddress from; /** Constructs a new Mail connection with the given parameters. */ protected MailReceiverConnection(Message requestMessage, Session session) { Assert.notNull(requestMessage, "'requestMessage' must not be null"); Assert.notNull(session, "'session' must not be null"); this.requestMessage = requestMessage; this.session = session; } /** Returns the request message for this connection. */ public Message getRequestMessage() { return requestMessage; } /** Returns the response message, if any, for this connection. */ public Message getResponseMessage() { return responseMessage; } /* * Package-friendly setters */ void setTransportUri(URLName transportUri) { this.transportUri = transportUri; } void setFrom(InternetAddress from) { this.from = from; } /* * URI */ @Override public URI getUri() throws URISyntaxException { try { Address[] recipients = requestMessage.getRecipients(Message.RecipientType.TO); if (!ObjectUtils.isEmpty(recipients) && recipients[0] instanceof InternetAddress) { return MailTransportUtils.toUri((InternetAddress) recipients[0], requestMessage.getSubject()); } else { throw new URISyntaxException("", "Could not determine To header"); } } catch (MessagingException ex) { throw new URISyntaxException("", ex.getMessage()); } } /* * Errors */ @Override public String getErrorMessage() throws IOException { return null; } @Override public boolean hasError() throws IOException { return false; } /* * Receiving */ @Override public Iterator<String> getRequestHeaderNames() throws IOException { try { List<String> headers = new ArrayList<String>(); Enumeration<?> enumeration = requestMessage.getAllHeaders(); while (enumeration.hasMoreElements()) { Header header = (Header) enumeration.nextElement(); headers.add(header.getName()); } return headers.iterator(); } catch (MessagingException ex) { throw new IOException(ex.getMessage()); } } @Override public Iterator<String> getRequestHeaders(String name) throws IOException { try { String[] headers = requestMessage.getHeader(name); return Arrays.asList(headers).iterator(); } catch (MessagingException ex) { throw new MailTransportException(ex); } } @Override protected InputStream getRequestInputStream() throws IOException { try { return requestMessage.getInputStream(); } catch (MessagingException ex) { throw new MailTransportException(ex); } } @Override public void addResponseHeader(String name, String value) throws IOException { try { responseMessage.addHeader(name, value); if (TransportConstants.HEADER_CONTENT_TYPE.equals(name)) { responseContentType = value; } } catch (MessagingException ex) { throw new MailTransportException(ex); } } @Override protected OutputStream getResponseOutputStream() throws IOException { return responseBuffer; } /* * Sending */ @Override protected void onSendBeforeWrite(WebServiceMessage message) throws IOException { try { responseMessage = requestMessage.reply(false); responseMessage.setFrom(from); responseBuffer = new ByteArrayOutputStream(); } catch (MessagingException ex) { throw new MailTransportException(ex); } } @Override protected void onSendAfterWrite(WebServiceMessage message) throws IOException { Transport transport = null; try { responseMessage.setDataHandler( new DataHandler(new ByteArrayDataSource(responseContentType, responseBuffer.toByteArray()))); transport = session.getTransport(transportUri); transport.connect(); responseMessage.saveChanges(); transport.sendMessage(responseMessage, responseMessage.getAllRecipients()); } catch (MessagingException ex) { throw new MailTransportException(ex); } finally { MailTransportUtils.closeService(transport); } } private class ByteArrayDataSource implements DataSource { private byte[] data; private String contentType; public ByteArrayDataSource(String contentType, byte[] data) { this.data = data; this.contentType = contentType; } @Override public String getContentType() { return contentType; } @Override public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(data); } @Override public String getName() { return "ByteArrayDataSource"; } @Override public OutputStream getOutputStream() throws IOException { throw new UnsupportedOperationException(); } } }