View Javadoc

1   /*
2    * Copyright 2005-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.transport.mail;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.OutputStream;
24  import java.net.URI;
25  import java.net.URISyntaxException;
26  import java.util.ArrayList;
27  import java.util.Arrays;
28  import java.util.Enumeration;
29  import java.util.Iterator;
30  import java.util.List;
31  import javax.activation.DataHandler;
32  import javax.activation.DataSource;
33  import javax.mail.Address;
34  import javax.mail.Header;
35  import javax.mail.Message;
36  import javax.mail.MessagingException;
37  import javax.mail.Session;
38  import javax.mail.Transport;
39  import javax.mail.URLName;
40  import javax.mail.internet.InternetAddress;
41  
42  import org.springframework.util.Assert;
43  import org.springframework.util.ObjectUtils;
44  import org.springframework.ws.WebServiceMessage;
45  import org.springframework.ws.transport.AbstractReceiverConnection;
46  import org.springframework.ws.transport.TransportConstants;
47  import org.springframework.ws.transport.WebServiceConnection;
48  import org.springframework.ws.transport.mail.support.MailTransportUtils;
49  
50  /**
51   * Implementation of {@link WebServiceConnection} that is used for server-side Mail access. Exposes a {@link Message}
52   * request and response message.
53   *
54   * @author Arjen Poutsma
55   * @since 1.5.0
56   */
57  public class MailReceiverConnection extends AbstractReceiverConnection {
58  
59      private final Message requestMessage;
60  
61      private final Session session;
62  
63      private Message responseMessage;
64  
65      private ByteArrayOutputStream responseBuffer;
66  
67      private String responseContentType;
68  
69      private URLName transportUri;
70  
71      private InternetAddress from;
72  
73      /** Constructs a new Mail connection with the given parameters. */
74      protected MailReceiverConnection(Message requestMessage, Session session) {
75          Assert.notNull(requestMessage, "'requestMessage' must not be null");
76          Assert.notNull(session, "'session' must not be null");
77          this.requestMessage = requestMessage;
78          this.session = session;
79      }
80  
81      /** Returns the request message for this connection. */
82      public Message getRequestMessage() {
83          return requestMessage;
84      }
85  
86      /** Returns the response message, if any, for this connection. */
87      public Message getResponseMessage() {
88          return responseMessage;
89      }
90  
91      /*
92       * Package-friendly setters
93       */
94      void setTransportUri(URLName transportUri) {
95          this.transportUri = transportUri;
96      }
97  
98      void setFrom(InternetAddress from) {
99          this.from = from;
100     }
101 
102     /*
103      * URI
104      */
105 
106     public URI getUri() throws URISyntaxException {
107         try {
108             Address[] recipients = requestMessage.getRecipients(Message.RecipientType.TO);
109             if (!ObjectUtils.isEmpty(recipients) && recipients[0] instanceof InternetAddress) {
110                 return MailTransportUtils.toUri((InternetAddress) recipients[0], requestMessage.getSubject());
111             }
112             else {
113                 throw new URISyntaxException("", "Could not determine To header");
114             }
115         }
116         catch (MessagingException ex) {
117             throw new URISyntaxException("", ex.getMessage());
118         }
119     }
120 /*
121      * Errors
122      */
123 
124     public String getErrorMessage() throws IOException {
125         return null;
126     }
127 
128     public boolean hasError() throws IOException {
129         return false;
130     }
131 
132     /*
133     * Receiving
134     */
135 
136     @Override
137     protected Iterator<String> getRequestHeaderNames() throws IOException {
138         try {
139             List<String> headers = new ArrayList<String>();
140             Enumeration<?> enumeration = requestMessage.getAllHeaders();
141             while (enumeration.hasMoreElements()) {
142                 Header header = (Header) enumeration.nextElement();
143                 headers.add(header.getName());
144             }
145             return headers.iterator();
146         }
147         catch (MessagingException ex) {
148             throw new IOException(ex.getMessage());
149         }
150     }
151 
152     @Override
153     protected Iterator<String> getRequestHeaders(String name) throws IOException {
154         try {
155             String[] headers = requestMessage.getHeader(name);
156             return Arrays.asList(headers).iterator();
157         }
158         catch (MessagingException ex) {
159             throw new MailTransportException(ex);
160         }
161     }
162 
163     @Override
164     protected InputStream getRequestInputStream() throws IOException {
165         try {
166             return requestMessage.getInputStream();
167         }
168         catch (MessagingException ex) {
169             throw new MailTransportException(ex);
170         }
171     }
172 
173     @Override
174     protected void addResponseHeader(String name, String value) throws IOException {
175         try {
176             responseMessage.addHeader(name, value);
177             if (TransportConstants.HEADER_CONTENT_TYPE.equals(name)) {
178                 responseContentType = value;
179             }
180         }
181         catch (MessagingException ex) {
182             throw new MailTransportException(ex);
183         }
184     }
185 
186     @Override
187     protected OutputStream getResponseOutputStream() throws IOException {
188         return responseBuffer;
189     }
190 
191     /*
192      * Sending
193      */
194 
195     @Override
196     protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
197         try {
198             responseMessage = requestMessage.reply(false);
199             responseMessage.setFrom(from);
200 
201             responseBuffer = new ByteArrayOutputStream();
202         }
203         catch (MessagingException ex) {
204             throw new MailTransportException(ex);
205         }
206     }
207 
208     @Override
209     protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
210         Transport transport = null;
211         try {
212             responseMessage.setDataHandler(
213                     new DataHandler(new ByteArrayDataSource(responseContentType, responseBuffer.toByteArray())));
214             transport = session.getTransport(transportUri);
215             transport.connect();
216             responseMessage.saveChanges();
217             transport.sendMessage(responseMessage, responseMessage.getAllRecipients());
218         }
219         catch (MessagingException ex) {
220             throw new MailTransportException(ex);
221         }
222         finally {
223             MailTransportUtils.closeService(transport);
224         }
225     }
226 
227     private class ByteArrayDataSource implements DataSource {
228 
229         private byte[] data;
230 
231         private String contentType;
232 
233         public ByteArrayDataSource(String contentType, byte[] data) {
234             this.data = data;
235             this.contentType = contentType;
236         }
237 
238         public String getContentType() {
239             return contentType;
240         }
241 
242         public InputStream getInputStream() throws IOException {
243             return new ByteArrayInputStream(data);
244         }
245 
246         public String getName() {
247             return "ByteArrayDataSource";
248         }
249 
250         public OutputStream getOutputStream() throws IOException {
251             throw new UnsupportedOperationException();
252         }
253     }
254 }