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 public void afterPropertiesSet() throws Exception {
135 Assert.notNull(storeUri, "Property 'storeUri' is required");
136 Assert.notNull(transportUri, "Property 'transportUri' is required");
137 if (monitoringStrategy == null) {
138 String protocol = storeUri.getProtocol();
139 if ("pop3".equals(protocol)) {
140 monitoringStrategy = new Pop3PollingMonitoringStrategy();
141 }
142 else if ("imap".equals(protocol)) {
143 monitoringStrategy = new PollingMonitoringStrategy();
144 }
145 else {
146 throw new IllegalArgumentException("Cannot determine monitoring strategy for \"" + protocol + "\". " +
147 "Set the 'monitoringStrategy' explicitly.");
148 }
149 }
150 super.afterPropertiesSet();
151 }
152
153 protected void onActivate() throws MessagingException {
154 openSession();
155 openFolder();
156 }
157
158 protected void onStart() {
159 if (logger.isInfoEnabled()) {
160 logger.info("Starting mail receiver [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
161 }
162 execute(new MonitoringRunnable());
163 }
164
165 protected void onStop() {
166 if (logger.isInfoEnabled()) {
167 logger.info("Stopping mail receiver [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
168 }
169 closeFolder();
170 }
171
172 protected void onShutdown() {
173 if (logger.isInfoEnabled()) {
174 logger.info("Shutting down mail receiver [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
175 }
176 closeFolder();
177 closeSession();
178 }
179
180 private void openSession() throws MessagingException {
181 store = session.getStore(storeUri);
182 if (logger.isDebugEnabled()) {
183 logger.debug("Connecting to store [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
184 }
185 store.connect();
186 }
187
188 private void openFolder() throws MessagingException {
189 if (folder != null && folder.isOpen()) {
190 return;
191 }
192 folder = store.getFolder(storeUri);
193 if (folder == null || !folder.exists()) {
194 throw new IllegalStateException("No default folder to receive from");
195 }
196 if (logger.isDebugEnabled()) {
197 logger.debug("Opening folder [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
198 }
199 folder.open(monitoringStrategy.getFolderOpenMode());
200 }
201
202 private void closeFolder() {
203 MailTransportUtils.closeFolder(folder, true);
204 }
205
206 private void closeSession() {
207 MailTransportUtils.closeService(store);
208 }
209
210 private class MonitoringRunnable implements SchedulingAwareRunnable {
211
212 public void run() {
213 try {
214 openFolder();
215 while (isRunning()) {
216 try {
217 Message[] messages = monitoringStrategy.monitor(folder);
218 for (int i = 0; i < messages.length; i++) {
219 MessageHandler handler = new MessageHandler(messages[i]);
220 execute(handler);
221 }
222 }
223 catch (FolderClosedException ex) {
224 logger.debug("Folder closed, reopening");
225 if (isRunning()) {
226 openFolder();
227 }
228 }
229 catch (MessagingException ex) {
230 logger.warn(ex);
231 }
232 }
233 }
234 catch (InterruptedException ex) {
235
236 Thread.currentThread().interrupt();
237 }
238 catch (MessagingException ex) {
239 logger.error(ex);
240 }
241 }
242
243 public boolean isLongLived() {
244 return true;
245 }
246 }
247
248 private class MessageHandler implements SchedulingAwareRunnable {
249
250 private final Message message;
251
252 public MessageHandler(Message message) {
253 this.message = message;
254 }
255
256 public void run() {
257 MailReceiverConnection connection = new MailReceiverConnection(message, session);
258 connection.setTransportUri(transportUri);
259 connection.setFrom(from);
260 try {
261 handleConnection(connection);
262 }
263 catch (Exception ex) {
264 logger.error("Could not handle incoming mail connection", ex);
265 }
266 }
267
268 public boolean isLongLived() {
269 return false;
270 }
271 }
272
273 }