1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.transport.mail;
18
19 import java.util.Properties;
20 import javax.mail.Folder;
21 import javax.mail.FolderClosedException;
22 import javax.mail.Message;
23 import javax.mail.MessagingException;
24 import javax.mail.Session;
25 import javax.mail.Store;
26 import javax.mail.URLName;
27 import javax.mail.internet.AddressException;
28 import javax.mail.internet.InternetAddress;
29
30 import org.springframework.scheduling.SchedulingAwareRunnable;
31 import org.springframework.util.Assert;
32 import org.springframework.ws.WebServiceMessageFactory;
33 import org.springframework.ws.transport.WebServiceMessageReceiver;
34 import org.springframework.ws.transport.mail.monitor.MonitoringStrategy;
35 import org.springframework.ws.transport.mail.monitor.PollingMonitoringStrategy;
36 import org.springframework.ws.transport.mail.monitor.Pop3PollingMonitoringStrategy;
37 import org.springframework.ws.transport.mail.support.MailTransportUtils;
38 import org.springframework.ws.transport.support.AbstractAsyncStandaloneMessageReceiver;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver {
54
55 private Session session = Session.getInstance(new Properties(), null);
56
57 private URLName storeUri;
58
59 private URLName transportUri;
60
61 private Folder folder;
62
63 private Store store;
64
65 private InternetAddress from;
66
67 private MonitoringStrategy monitoringStrategy;
68
69
70 public void setFrom(String from) throws AddressException {
71 this.from = new InternetAddress(from);
72 }
73
74
75
76
77
78
79
80
81
82 public void setJavaMailProperties(Properties javaMailProperties) {
83 session = Session.getInstance(javaMailProperties, null);
84 }
85
86
87
88
89
90
91
92
93
94
95
96
97 public void setSession(Session session) {
98 Assert.notNull(session, "Session must not be null");
99 this.session = session;
100 }
101
102
103
104
105
106
107
108
109
110 public void setStoreUri(String storeUri) {
111 this.storeUri = new URLName(storeUri);
112 }
113
114
115
116
117
118
119
120
121
122 public void setTransportUri(String transportUri) {
123 this.transportUri = new URLName(transportUri);
124 }
125
126
127
128
129
130 public void setMonitoringStrategy(MonitoringStrategy monitoringStrategy) {
131 this.monitoringStrategy = monitoringStrategy;
132 }
133
134 @Override
135 public void afterPropertiesSet() throws Exception {
136 Assert.notNull(storeUri, "Property 'storeUri' is required");
137 Assert.notNull(transportUri, "Property 'transportUri' is required");
138 if (monitoringStrategy == null) {
139 String protocol = storeUri.getProtocol();
140 if ("pop3".equals(protocol)) {
141 monitoringStrategy = new Pop3PollingMonitoringStrategy();
142 }
143 else if ("imap".equals(protocol)) {
144 monitoringStrategy = new PollingMonitoringStrategy();
145 }
146 else {
147 throw new IllegalArgumentException("Cannot determine monitoring strategy for \"" + protocol + "\". " +
148 "Set the 'monitoringStrategy' explicitly.");
149 }
150 }
151 super.afterPropertiesSet();
152 }
153
154 @Override
155 protected void onActivate() throws MessagingException {
156 openSession();
157 openFolder();
158 }
159
160 @Override
161 protected void onStart() {
162 if (logger.isInfoEnabled()) {
163 logger.info("Starting mail receiver [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
164 }
165 execute(new MonitoringRunnable());
166 }
167
168 @Override
169 protected void onStop() {
170 if (logger.isInfoEnabled()) {
171 logger.info("Stopping mail receiver [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
172 }
173 closeFolder();
174 }
175
176 @Override
177 protected void onShutdown() {
178 if (logger.isInfoEnabled()) {
179 logger.info("Shutting down mail receiver [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
180 }
181 closeFolder();
182 closeSession();
183 }
184
185 private void openSession() throws MessagingException {
186 store = session.getStore(storeUri);
187 if (logger.isDebugEnabled()) {
188 logger.debug("Connecting to store [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
189 }
190 store.connect();
191 }
192
193 private void openFolder() throws MessagingException {
194 if (folder != null && folder.isOpen()) {
195 return;
196 }
197 folder = store.getFolder(storeUri);
198 if (folder == null || !folder.exists()) {
199 throw new IllegalStateException("No default folder to receive from");
200 }
201 if (logger.isDebugEnabled()) {
202 logger.debug("Opening folder [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
203 }
204 folder.open(monitoringStrategy.getFolderOpenMode());
205 }
206
207 private void closeFolder() {
208 MailTransportUtils.closeFolder(folder, true);
209 }
210
211 private void closeSession() {
212 MailTransportUtils.closeService(store);
213 }
214
215 private class MonitoringRunnable implements SchedulingAwareRunnable {
216
217 public void run() {
218 try {
219 openFolder();
220 while (isRunning()) {
221 try {
222 Message[] messages = monitoringStrategy.monitor(folder);
223 for (Message message : messages) {
224 MessageHandler handler = new MessageHandler(message);
225 execute(handler);
226 }
227 }
228 catch (FolderClosedException ex) {
229 logger.debug("Folder closed, reopening");
230 if (isRunning()) {
231 openFolder();
232 }
233 }
234 catch (MessagingException ex) {
235 logger.warn(ex);
236 }
237 }
238 }
239 catch (InterruptedException ex) {
240
241 Thread.currentThread().interrupt();
242 }
243 catch (MessagingException ex) {
244 logger.error(ex);
245 }
246 }
247
248 public boolean isLongLived() {
249 return true;
250 }
251 }
252
253 private class MessageHandler implements SchedulingAwareRunnable {
254
255 private final Message message;
256
257 public MessageHandler(Message message) {
258 this.message = message;
259 }
260
261 public void run() {
262 MailReceiverConnection connection = new MailReceiverConnection(message, session);
263 connection.setTransportUri(transportUri);
264 connection.setFrom(from);
265 try {
266 handleConnection(connection);
267 }
268 catch (Exception ex) {
269 logger.error("Could not handle incoming mail connection", ex);
270 }
271 }
272
273 public boolean isLongLived() {
274 return false;
275 }
276 }
277
278 }